winforms 修复拖放冻结资源管理器

3duebb1j  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(96)

我有一个应用程序,它允许在对它执行可能非常长的操作之前将数据拖放到其中。这工作正常,但是,资源管理器窗口冻结,而我的应用程序正在处理。有没有办法“释放”它可以这么说,只要我已经采取了文件列表的副本?
我现在的代码是:

private void MainForm_DragDrop(object sender, DragEventArgs e)
    {
        ClearTempFiles(); //Clear all files before populating
        string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); //Get the filepaths for the dragdrop data
        List<string> toParse = new List<string>();
        foreach (string file in files) 
        {
            FileAttributes attr = File.GetAttributes(file);
            if (attr.HasFlag(FileAttributes.Directory)) //If a folder has been included, add all files from within
            {
                toParse.AddRange(DirSearch(file));
            }
            else
            {
                toParse.Add(file); //Add files
            }
        }
        CurrentJobData = new JobData(toParse); //Create new JobData from these files <---- Takes up to a few minutes with hundreds of files.
        CurrentJobData.ToTree(treeView1); //Push this data to the TreeView
    } //Handles the dragdrop of data, populating the solution
y4ekin9u

y4ekin9u1#

您需要让事件运行到完成。由于DragDrop操作的性质,所涉及的两个应用程序都需要确保操作已经完成。它们只能判断DragDrop消息是否由任一消息泵处理。只要这种情况没有发生,Explorer就只能假设用户仍然在拖放。因此,正如在评论中已经建议的那样,使用BackgroundWorker:

private void Form1_DragDrop(object sender, DragEventArgs e)
{    
    // gets all data from Explorer
    string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); //Get the filepaths for the dragdrop data

    // don't block the UI thread, that prevents the 
    // processing of both Windows messages in Explorer and your app
    // to complete, effectively blocking both of them
    backgroundWorker1.RunWorkerAsync(files);

    // if you want your form to be unavailable
    // while processing takes place
    // set Enabled to false on your form
    this.Enabled = false;
}

您是DoWork事件处理程序,现在将完成繁重的工作。请注意我如何设置DoWorkEventArgsResult属性以将JobData发送到completed事件。

// this all runs on a background, non-UI threed
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    ClearTempFiles(); //Clear all files before populating

    string[] files = (string[])e.Argument; // this is passed in from RunWorkerAsync

    List<string> toParse = new List<string>();
    foreach (string file in files)
    {
        FileAttributes attr = File.GetAttributes(file);
        if (attr.HasFlag(FileAttributes.Directory)) //If a folder has been included, add all files from within
        {
            toParse.AddRange(DirSearch(file));
        }
        else
        {
            toParse.Add(file); //Add files
        }
    }

    e.Result = new JobData(toParse); //Create new JobData from these files <---- Takes up to a few minutes with hundreds of files.
}

RunWorkerCompleted事件处理程序中,您可以回到UI线程,在那里您可以填充和更新TreeView。请注意,在最后表单是如何再次启用的,以确保用户可以与应用程序交互。

// this runs on the UI thread
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    CurrentJobData = (JobData) e.Result;

    CurrentJobData.ToTree(treeView1); //Push this data to the TreeView

    // set Enabled to true on your controls
    this.Enabled = true;
}

如果要报告进度,请确保使用ProgressChanged事件处理程序,这样您就处于UI线程上,并在backgroundworker上调用ReportProgress方法来调用该处理程序。

ezykj2lf

ezykj2lf2#

我已经创建了一个基于backgroundworker的通用视图(wpf),它带有一个进度条,用来显示需要一些时间的任务的进度。我称之为“AjaxDialog”。我在一个应用程序中使用了这个视图,它通过拖放操作自动启动一个需要一些时间的任务。我也遇到了同样的问题,因为我已经用ShowDialog()启动了AjaxDialog,浏览器被冻结,直到我的“AjaxDialog”再次关闭-即使任务是在后台工作程序中执行的。
我是这样解决的:

private void Panel_OnDrop(object sender, DragEventArgs e)
    {
        new TaskFactory().StartNew(() =>
        {
            Thread.Sleep(200); //wait for drop event to be handled (freeze of explorer)

            //go back to ui thread and execute task
            Application.Current.Dispatcher.Invoke(() =>
            {
                //this method creates an instance of my AjaxDialog, passes the status text
                //and the action to execute to its background worker and calls ShowDialog()
                AjaxDialog.PerformTask("Waiting for task to be finished", (s, args) =>
                {
                    //do stuff here
                });
            });
        });
    }

相关问题