我有一个应用程序,它允许将数据拖放到其中,然后再对其执行可能很长的操作。这工作正常,但是,当我的应用程序正在处理时,资源管理器窗口会冻结。有没有什么办法可以“释放”它,只要我复制了文件列表?
我目前的代码是:
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
Run Code Online (Sandbox Code Playgroud)
您需要让事件运行完成。由于 DragDrop 操作的性质,涉及的两个应用程序都需要确保操作已完成。他们只能判断 DragDrop 消息是否由任一消息泵处理。只要这种情况没有发生,资源管理器就只能假设用户仍在拖放。正如评论中已经建议的那样,使用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;
}
Run Code Online (Sandbox Code Playgroud)
您作为DoWork事件处理程序现在将承担繁重的工作。请注意我如何设置Result的属性DoWorkEventArgs以将您的 JobData 发送到已完成的事件。
// 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.
}
Run Code Online (Sandbox Code Playgroud)
在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;
}
Run Code Online (Sandbox Code Playgroud)
如果要报告进度,请确保使用 ProgressChanged 事件处理程序,以便您位于 UI 线程上并调用ReportProgress后台工作程序上的方法来调用该处理程序。