对于背景工作者在预期时不停止感到困惑

时间:2017-02-05 00:16:21

标签: c# winforms backgroundworker

我有以下代码。它只是一个表单应用程序。在加载时,它将运行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();
}

1 个答案:

答案 0 :(得分:2)

您正在阻止UI线程,这会阻止BackgroundWorker完成。在UI线程可以自由处理新消息之前,它不能引发RunWorkerCompleted事件(引发事件涉及将消息发布到UI线程的消息队列,以便UI线程可以执行实际的代码举起活动。)

您的代码也存在缺陷,因为它正在从工作线程调用Application.DoEvents()。无论如何你应该从不调用这个方法,但是从工作线程调用它是特别愚蠢的,因为拥有一个工作线程的全部意义是避免必须调用该方法(并且它不会无论如何在工作线程上调用时都要做任何事情,因为工作线程不应该拥有需要接收窗口消息的任何窗口对象。)

不要坐在繁忙的循环中,检查IsBusy并阻止UI线程,您应该只订阅RunWorkerCompleted事件并做任何您需要做的事情。如果没有一个好的Minimal, Complete, and Verifiable code example充分说明你实际上要做的事情,那么就不可能提供比这更具体的建议。