簡體   English   中英

后台工作者RunWorkCompleted事件

[英]Background worker RunWorkCompleted Event

我有以下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
    }
}

雖然建議使用“任務”的答案會起作用,但對於為什么要等到后台工作人員完成其工作之后再讓UI線程的click事件繼續,我有些困惑。 據我了解,您使用后台工作程序是因為您要執行后台工作而不阻塞UI。 您提出問題的方式表明您想在完成工作之前阻止UI。 在這種情況下,為什么還要使用單獨的線程?

另外,關於您的評論:

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

我假設如果不加注釋,則UI會永久阻塞? 當您在按鈕的click事件中調用autoReset.WaitOne()時,您正在阻塞UI線程。 盡管DoWork將在后台線程上運行,但RunWorkerCompleted事件在UI線程上運行。 因此RunWorkerCompleted將永遠無法執行。

如果您評論WaitOne()調用,我認為它根本不會“正確”地工作。 我對其進行了測試,由於UI線程和后台線程之間存在競爭,因此它在click-> load-> completed和load-> click-> completed之間有所不同。

使用任務,並使用ContinueWith方法: https : //msdn.microsoft.com/zh-cn/library/dd270696(v=vs.110).aspx

我想以下應該給出所需的行為-

 private void btnAnalyze_Click(object sender, RoutedEventArgs e)
 {      

       Task.Factory.StartNew(() => {   

       })
       .ContinueWith(f => {            

       })
       .Wait(); 
 }

這里的大多數答案正確地要求您嘗試使用TPL進行操作,但是,如果您遇到的復雜情況是需要使用ManualResetEvent / AutoResetEvent,那么這里就是您解決問題的方法。 只需將btn click邏輯包含在“任務”或線程中即可。 想法是您不想保留UI(STA Main)線程。 這導致某些運行時優化,並導致不良行為。

Task.Factory.StartNew(() =>
            {
                bwAnalyzer.RunWorkerAsync(); //#1
                autoReset.WaitOne(); //when commented working properly
                Console.WriteLine("click"); //#4
            });

上面的代碼片段應該給您想要的行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM