我正在嘗試運行以下代碼來測驗BackgroundWorker,但這給我帶來了很多問題:
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
namespace BackgroundWorkingTest
{
public partial class Form1 : Form
{
BackgroundWorker backgroundWorker1 = new BackgroundWorker();
int counter;
public Form1()
{
InitializeComponent();
backgroundWorker1 = new BackgroundWorker
{
WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
backgroundWorker1.DoWork = BackgroundWorker1_DoWork;
backgroundWorker1.ProgressChanged = BackgroundWorker1_ProgressChanged;
backgroundWorker1.RunWorkerCompleted = BackgroundWorker1_RunWorkerCompleted;
}
private void StartButton_Click(object sender, EventArgs e) // Start
{
counter = 0;
backgroundWorker1.RunWorkerAsync();
}
private void CancelButton_Click(object sender, EventArgs e) // Cancel
{
backgroundWorker1.CancelAsync();
progressLabel.Text = "0";
}
private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e) // DoWork
{
int i;
for (i = 0; i < 123456; i )
{
// Application.DoEvents(); // This line doesn't help
// Thread.Sleep(1); // Enable this line solve the problem
backgroundWorker1.ReportProgress(i 1);
counter ;
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
return;
}
}
}
private void BackgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) // Progress
{
progressLabel.Text = counter.ToString();
progressLabel.Refresh();
}
private void BackgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) // Completed
{
if (e.Cancelled)
MessageBox.Show("Operation Cancelled");
else
MessageBox.Show("Operation Completed");
}
}
}
1、例如在BackgroundWorker1_DoWork()方法中可以看到命令:
Thread.Sleep(1);
如果我禁用它,則“取消”按鈕沒有回應。我單擊它幾次,但它沒有停止該程序,并且我沒有收到“操作已取消”訊息。
如果我啟用它,那么它就可以作業,但我不想在我的執行緒中使用任何 Sleep(1) 命令,因為它只會減慢行程,我不希望這樣。
如果我啟用命令:
Application.DoEvents();
它根本沒有幫助,并且“取消”按鈕在計數期間也沒有回應。
2.我看到的另一個問題是,如果我使用以下命令:
progressLabel.Refresh();
在 ProgressChanged() 事件中,發生了一些非常奇怪的事情。我可以在面板上看到它完成了計數,并在標簽上顯示:“123456”。但在那之后幾乎需要一分鐘,它才會向我顯示“操作已完成”訊息。
如果在標簽顯示“123456”之后,我在 ProgressChanged() 方法中設定了一個斷點,那么我看到它不斷進入該方法,并且 e.ProgressPercentage 引數一直在上升。
怎么會這樣?如果我在面板上看到“123456”,它不是說該程序已完成嗎?如果是這樣,那么為什么它不立即向我顯示“操作已完成”訊息?
3.如果我洗掉“progressLabel.Refresh()”行,那么在標簽顯示“123456”后我會立即收到“操作完成”訊息,但它不會顯示 0 到 123456 之間的計數(正如我在啟用 Refresh() 命令時看到的那樣)。
4.另一件我不太明白的事:
當我更改代碼以使用多個 BackgroundWorkers 而不是一個陣列時:
BackgroundWorker[] backgroundWorker1 = new ....
啟用 Sleep(1) 后,我沒有收到任何錯誤訊息,盡管所有執行緒都將文本設定為相同的標簽,并將值寫入相同的計數器。
這有意義嗎?從多個 BackgroundWorker 執行緒同時更新同一個標簽時,我怎么沒有收到任何運行時錯誤?
非常感謝。
uj5u.com熱心網友回復:
您過于頻繁地報告進度:
for (i = 0; i < 123456; i )
{
backgroundWorker1.ReportProgress(i 1);
...并且視窗的訊息回圈被訊息溢位。所以它不能CancelButton_Click及時為事件服務。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/506813.html
