【问题标题】:Waiting for either of these BackgroundWorker to complete等待这些 BackgroundWorker 中的任何一个完成
【发布时间】:2010-02-02 01:39:38
【问题描述】:

应该使用服务下载 FORM(某些 UI)的序列。 目前,此下载位于 BackgroundWorker 线程中。 现在,由于性能很慢......我们决定将 FORMS 分为 2 类,并开始使用现有线程之上的另一个 BackgroundWorker 并行下载。

现在,场景是这个 BackgroundWorker 应该等待另一个完成。 那么,如何实现呢。

我尝试使用 AutoResetEvent。但是,我无法做到这一点。

感谢任何帮助。

【问题讨论】:

    标签: c# .net multithreading backgroundworker


    【解决方案1】:

    我不认为这种情况真的是一个BackgroundWorker 应该等待另一个。您真正想要的是在它们都完成之后(并且仅在之后)触发一些 UI 事件。这是一个微妙但重要的区别。第二个版本更容易编码。

    public class Form1 : Form
    {
        private object download1Result;
        private object download2Result;
    
        private void BeginDownload()
        {
            // Next two lines are only necessary if this is called multiple times
            download1Result = null;
            download2Result = null;
    
            bwDownload1.RunWorkerAsync();
            bwDownload2.RunWorkerAsync();
        }
    
        private void bwDownload1_RunWorkerCompleted(object sender,
            RunWorkerCompletedEventArgs e)
        {
            download1Result = e.Result;
            if (download2Result != null)
                DisplayResults();
        }
    
        private void bwDownload2_RunWorkerCompleted(object sender,
            RunWorkerCompletedEventArgs e)
        {
            download2Result = e.Result;
            if (download1Result != null)
                DisplayResults();
        }
    
        private void DisplayResults()
        {
            // Do something with download1Result and download2Result
        }
    }
    

    注意那些object 引用应该是强类型的,我只是使用object 因为我不知道你在下载什么。

    这真的是你所需要的; RunWorkerCompleted 事件在前台线程中运行,因此您实际上不必担心那里的同步或竞争条件。不需要lock 语句、AutoResetEvent 等。只需使用两个成员变量来保存结果,或者如果两者的结果实际上可以是null,则使用两个布尔标志。

    【讨论】:

    • 这是正确的答案。 +1
    【解决方案2】:

    您应该能够使用两个 AutoResetEvent 和 WaitAll 函数来等待两者完成。在相应的OnRunWorkerCompleted 事件中调用 AutoResetEvent 对象上的Set 函数。

    【讨论】:

      【解决方案3】:

      Jeffrey Richter 是多线程方面的大师,他编写了一个名为 Power Threading Library 的出色库,它可以执行诸如异步下载 n 个文件并在它们全部完成(或一个或一些)后继续执行等任务,非常简单。

      花点时间观看视频,了解它,您不会后悔的。使用强大的线程库(免费并且还具有 Silverlight 和 Compact Framework 版本)还可以使您的代码更易于阅读,这在执行任何异步操作时是一个很大的优势。

      祝你好运, 标记

      【讨论】:

        【解决方案4】:
        int completedCount = 0;
        
        void threadProc1() { //your thread1 proc
        //do something
        ....
        
        completedCount++;
        while (completedCount < 2) Thread.Sleep(10);
        //now both threads are done
        }
        
        void threadProc2() { //your thread1 proc
        //do something
        ....
        
        completedCount++;
        while (completedCount < 2) Thread.Sleep(10);
        //now both threads are done
        }
        

        【讨论】:

          【解决方案5】:

          只需使用 2 个 BackgroundWorker 对象,并让每个对象在完成时向 UI 发出警报。这样,您可以在 UI 上显示微调器、进度条等任何内容,并在下载结果从线程返回时对其进行更新。您还将避免任何线程死锁等风险。

          顺便说一下,我们都清楚,你不应该从 UI 线程调用诸如 WaitAll 之类的阻塞函数。它会导致 UI 完全锁定,这会让你的用户怀疑 WTF 正在发生:)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-07-23
            相关资源
            最近更新 更多