后台工作者RunWorkCompleted事件

时间:2015-05-06 05:16:42

标签: c# wpf multithreading backgroundworker

我有以下wpf程序,我想做的是btnAnalyzer_click方法等待DoWork& RunWorkerCompleted方法完成。所以我使用了AutoResetEvent,但现在bwAnalyze_click方法(#4行)在DoWork之后运行,然后运行WorkerCompleted方法(行顺序 - #1#2#4&#3)。但是我希望它们按照#1#2#3&的顺序执行。 #4。任何解决方案或建议?

public partial class MainWindow : Window
{
    private readonly BackgroundWorker bwAnalyzer = new BackgroundWorker();
    private AutoResetEvent autoReset;//to signal the end of the BackgroudnWork

    public MainWindow()
    {
        InitializeComponent();
        autoReset = new AutoResetEvent(false);
        bwAnalyzer.DoWork += new DoWorkEventHandler(DoWork);
        bwAnalyzer.RunWorkerCompleted += new RunWorkerCompletedEventHandler(WorkerCompleted);
    }

    void WorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Console.WriteLine("Completed"); #3
        autoReset.Set();
    }

    void DoWork(object sender, DoWorkEventArgs e)
    {
        Console.WriteLine("load"); #2

    }

    private void btnAnalyze_Click(object sender, RoutedEventArgs e)
    {
        bwAnalyzer.RunWorkerAsync(); #1
        autoReset.WaitOne();//when commented working properly
        Console.WriteLine("click"); #4
    }
}

4 个答案:

答案 0 :(得分:2)

虽然建议使用Tasks的答案可行,但我有点困惑为什么要等到后台工作人员完成其工作之后才让UI线程的点击事件继续。据我所知,您使用后台工作程序,因为您希望在不阻止UI的情况下执行后台工作。您提出问题的方式表明您希望在工作完成之前阻止UI。在这种情况下,为什么要使用单独的线程?

另外,关于你的评论:

autoReset.WaitOne();//when commented working properly

我假设如果您将其取消注释,UI会永久阻止?当您在按钮的单击事件中调用autoReset.WaitOne()时,您将阻止UI线程。虽然DoWork将在后台线程上运行,但RunWorkerCompleted事件在UI线程上运行。因此RunWorkerCompleted永远不会执行。

如果您对WaitOne()来电发表评论,我认为它根本不会“正常”发挥作用。我测试了它,并且由于UI线程和后台线程之间的竞争而在click-> load-> completed和load-> click->完成之间变化。

答案 1 :(得分:1)

使用任务,并使用ContinueWith方法:https://msdn.microsoft.com/en-us/library/dd270696(v=vs.110).aspx

答案 2 :(得分:1)

我想以下内容应该给出所需的行为 -

 private void btnAnalyze_Click(object sender, RoutedEventArgs e)
 {      

       Task.Factory.StartNew(() => {   

       })
       .ContinueWith(f => {            

       })
       .Wait(); 
 }

答案 3 :(得分:0)

这里的大多数答案都正确地要求您尝试使用TPL做您想做的事情,但如果您有一个复杂的场景,您需要使用ManualResetEvent / AutoResetEvent,那么这里就是解决您问题的方法。 只需在任务或线程中包含您的btn click逻辑。想法是你不想持有UI(STA Main)线程。这导致一些运行时优化并导致不期望的行为。

write.table(...)

只要拥有上述代码段就可以为您提供所需的行为。