为什么我的多线程卡住了我的UI和BackgroundWorker工作
本文关键字:我的 BackgroundWorker 工作 UI 多线程 为什么 | 更新日期: 2023-09-27 18:21:31
我有Winforms
应用程序,它读取几个网络文件夹并搜索其中的文件:
public void test(List<string> folders, decimal numberOfFiles)
{
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.DoWork += new DoWorkEventHandler(
(s3, e3) =>
{
foreach (string folder in folders)
{
if (Directory.Exists(folder))
{
var files = Directory.EnumerateFiles(folder, "*.doc", SearchOption.TopDirectoryOnly)
.OrderByDescending(x => new FileInfo(x).CreationTime).Take((int)numberOfFiles).ToList<string>();
if (files.Count != 0)
{
foreach (string file in files)
{
ProcessMyFile(file); // Check my file and if this file OK raised event the main UI and add this file into my `ListView`
}
}
}
}
});
backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
(s3, e3) =>
{
// Finish search all folders
}
);
backgroundWorker.RunWorkerAsync();
}
该功能接收文件夹列表并搜索x个最新文件,结果是小列表(来自每个文件夹),它将通过另一个功能(ProcessMyFile)进行检查,如果文件OK将事件引发到我的主UI,并以这种方式搜索所有这些文件:
private AddFile(string file)
{
this.Invoke((MethodInvoker)delegate
{
// bla bla
});
}
这很好,但因为我有很多文件,而且test
每次只检查一个文件,所以我想改进它以支持Multi Threading
sop,我有这样的功能:
public void test2(List<string> folders, decimal numberOfFiles)
{
foreach (string folder in folders)
{
int numThreads = 10;
ManualResetEvent resetEvent = new ManualResetEvent(false);
int toProcess = numThreads;
// Start workers.
for (int i = 0; i < numThreads; i++)
{
new Thread(delegate()
{
if (Directory.Exists(folder))
{
var files = Directory.EnumerateFiles(folder, "*.doc", SearchOption.TopDirectoryOnly)
.OrderByDescending(x => new FileInfo(x).CreationTime).Take((int)numberOfFiles).ToList<string>();
if (files.Count != 0)
{
foreach (string file in files)
{
ProcessMyFile(file);
}
}
}
// If we're the last thread, signal
if (Interlocked.Decrement(ref toProcess) == 0)
resetEvent.Set();
}).Start();
}
// Wait for workers.
resetEvent.WaitOne();
}
}
我的问题是,尽管这个函数将文件返回到主UI中的AddFile
函数中,但我的所有UI都被破坏了,我不知道为什么。
启动所有线程后,用resetEvent.WaitOne()
阻塞UI线程。因此,即使您在UI线程上调用// bla bla
,它也无法处理它,因为它被阻塞了。
您不应该创建线程,而应该研究Task<T>
。它以一种更复杂的方式处理您的后台工作,并且能够自动将您的延续代码分配给UI线程。