簡體   English   中英

使用BackgroundWorker進行表單凍結

[英]Form freezing using BackgroundWorker

我正在使用WinForm,從中我需要的所有進程都被引導。 現在我正在嘗試將BackgroundWorkerProgressBar和取消按鈕集成到我的代碼中。 我希望它在我的代碼本地,而不是在一個單獨的方法。 要對此進行測試,將創建一個帶有進度條(尚未激活)的新表單和一個用於停止for循環的按鈕。 但是,代碼無法正常工作(甚至還沒有包含進度條)。 表格立即凍結(見圖)所以我無法測試取消按鈕。 然而,執行for循環並顯示"Done: " + l.ToString() 我怎么解決這個問題?

void stopMeasurement(object sender, EventArgs e) 
{
    stopMeas = true;    
}

public void testcancel() // Test method which is triggered manually
{
    int l = 0;

    MetingProgress metingProgress = new MetingProgress();
    metingProgress.btnCancelmeting.Click += new EventHandler(stopMeasurement);

    BackgroundWorker worker = new BackgroundWorker();
    worker.WorkerSupportsCancellation = true;
    worker.DoWork += (sender, args) =>
    {                       
        for (int k = 0; k < 10; k++)
        {
            Thread.Sleep(1000);
            l++;

            if (worker.CancellationPending)
                break;
        }

        MessageBox.Show("Done: " + l.ToString());

    };
    worker.RunWorkerAsync(); 

    while (worker.IsBusy) 
    {
        if (stopMeas)
            worker.CancelAsync();
    }

    metingProgress.Dispose();
    MessageBox.Show("All done");

}

在此輸入圖像描述

這段代碼是你的問題:

while (worker.IsBusy) 
{
    if (stopMeas)
        worker.CancelAsync();
}

你的GUI-Thread就在那個循環中,直到你的工作完成。 您需要從EventHandler中訪問您的worker實例,並從那里調用worker.CancelAsync()。


除此之外,我個人會分兩步改進代碼:

  1. 將整個BackgroundWorker移動到MetingProgress類中,並使其構造函數為實際工作實現提供委托。

  2. 使用TAP(任務異步模式),即async / await Task with Progress和CancellationToken。

表格立即凍結

這是因為你有一個while循環仍在主線程上運行! 因此表單不會響應。 這叫做buisy等待。 您將無法調用CancelAsync方法。

一種解決方案可能是刪除while循環並將取消調用放入按鈕事件代碼中:

void stopMeasurement(object sender, EventArgs e)
{
    stopMeas = true;
    worker.CancelAsync();

}

你基本上做的是:你創建了第二個取消令牌。 所以另一種可能性是只使用stopMeas來取消后台操作:

worker.DoWork += (sender, args) =>
{                       
    for (int k = 0; k < 10; k++)
    {
        Thread.Sleep(1000);
        l++;

        if (stopMeas)
            break;
    }

    string mes = stopMeas ? "Done: " + l.ToString() : "Task aborted!";
    MessageBox.Show(mes);

};

編輯:這一行:

metingProgress.Dispose();

可能會導致ObjectDisposed異常。 如果后台進程仍在運行並嘗試更新進度條,則您已經處理了該表單。 您應該刪除此行並將其留給垃圾收集器。

暫無
暫無

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

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