为什么我的多线程卡住了我的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都被破坏了,我不知道为什么。

为什么我的多线程卡住了我的UI和BackgroundWorker工作

启动所有线程后,用resetEvent.WaitOne()阻塞UI线程。因此,即使您在UI线程上调用// bla bla,它也无法处理它,因为它被阻塞了。

您不应该创建线程,而应该研究Task<T>。它以一种更复杂的方式处理您的后台工作,并且能够自动将您的延续代码分配给UI线程。