我有以下代码。它只是一个表单应用程序。在加载时,它将运行bacground worker。
然后我有一个按钮,它应该通过将标志设置为true来停止后台工作程序中的无限循环。
我正在记录backgroundworker1.IsBusy
的输出并且它说它很忙但是根据我的代码中的逻辑它不应该忙,因为我将标志设置为true从而退出while循环并且正在运行backgroundworker_Completed
事件。
我一定是做错了什么但我无法理解。
如果我接近这个错误,有人可以帮助我解决我做错的事情,或者指出我如何能够完成我在这里尝试做的事情。
private volatile bool StopScanning = false;
private void myForm_Load(object sender, EventArgs e)
{
try
{
if (backgroundWorker1.IsBusy)
{
//do nothing
}
else
{
backgroundWorker1.RunWorkerAsync();
}
}
catch (Exception boo)
{
Log.log(boo.ToString());
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while (StopScanning == false)
{
Application.DoEvents();
try
{
ReturnScannedItems();
System.Threading.Thread.Sleep(1000);
}
catch (Exception boo)
{
Log.log(boo.ToString());
}
}
}
private void cancelbutton_Click(object sender, EventArgs e)
{
try
{
Log.log("Setting Stop Scan flag to true");
StopScanning = true;
Log.log(CloseScanSession().ToString());
}
catch (Exception boo)
{
Log.log("Setting Stop Scan flag to true");
StopScanning = true;
Log.log(CloseScanSession().ToString());
Log.log(boo.ToString());
}
while (backgroundWorker1.IsBusy)
{
Log.log("Still busy");
}
this.Close();
}
答案 0 :(得分:2)
您正在阻止UI线程,这会阻止BackgroundWorker
完成。在UI线程可以自由处理新消息之前,它不能引发RunWorkerCompleted
事件(引发事件涉及将消息发布到UI线程的消息队列,以便UI线程可以执行实际的代码举起活动。)
您的代码也存在缺陷,因为它正在从工作线程调用Application.DoEvents()
。无论如何你应该从不调用这个方法,但是从工作线程调用它是特别愚蠢的,因为拥有一个工作线程的全部意义是避免必须调用该方法(并且它不会无论如何在工作线程上调用时都要做任何事情,因为工作线程不应该拥有需要接收窗口消息的任何窗口对象。)
不要坐在繁忙的循环中,检查IsBusy
并阻止UI线程,您应该只订阅RunWorkerCompleted
事件并做任何您需要做的事情。如果没有一个好的Minimal, Complete, and Verifiable code example充分说明你实际上要做的事情,那么就不可能提供比这更具体的建议。