停止线程由backgroundworker启动

时间:2015-07-17 19:57:44

标签: c# winforms backgroundworker

我有一个使用背景工作者的窗体。 backgroundworker实例化一个对象,然后在该对象中执行一个方法。我的问题是,当我使用backgroundworker.CancelAsync时,在远程对象上运行的方法不会停止。在下面的示例中,单击按钮取消后,dowork方法继续执行。仅供参考,dowork通过电子表格循环并根据电子表格中的行进行一些数据操作。

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        myObject newObject = new myObject();
        newObject.dowork();

        if (backgroundWorker1.CancellationPending)
        {
            e.Cancel = true;
            backgroundWorker1.ReportProgress(0);
            return;
        }
    }

     private void btnCancel_Click(object sender, EventArgs e)
    {
       if (backgroundWorker1.IsBusy) backgroundWorker1.CancelAsync();
    }

思想?

由于

1 个答案:

答案 0 :(得分:2)

btnCancel_Click中,您必须将取消请求传递给您的工作人员对象;否则,它将永远不会被通知。 BackgroundWorker.CancelAsync()只是简单地设置BackgroundWorker.CancellationPending属性,通知背景工作者的消费者(UI,而不是已执行的任务)您的任务已被取消,它不会做任何事情。

所以你需要的是:

MyObject myObject;

// This method is executed on the worker thread. Do not access your controls
// in the main thread from here directly.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    myObject = new MyObject();

    // The following line is a blocking operation in this thread.
    // The user acts in the UI thread, not here, so you cannot do here
    // anything but wait.
    myObject.DoWork();

    // Now DoWork is finished. Next line is needed only to notify
    // the caller of the event whether a cancel has happened.
    if (backgroundWorker1.CancellationPending)
        e.Cancel = true;

    myObject = null;
}

private void btnCancel_Click(object sender, EventArgs e)
{
   if (backgroundWorker1.IsBusy)
   {
       backgroundWorker1.CancelAsync();

       // You must notify your worker object as well.
       // Note: Now you access the worker object from the main thread!
       // Note2: It would be possible to pass the worker to your object
       //        and poll the backgroundWorker1.CancellationPending from there,
       //        but that would be a nasty pattern. BL objects should not
       //        aware of the UI components.
       myObject.CancelWork();
   }
}

您应该如何实施通知:

public class MyObject
{
    // normally you should use locks to access fields from different threads
    // but if you just set a bool from one thread and read it from another,
    // then it is enough to use a volatile field.
    private volatile bool isCancelRequested;

    // this will be called from the main thread
    public void CancelWork()
    {
        isCancelRequested = true;
    }

    // This method is called from the worker thread.
    public void DoWork()
    {
        // Make sure you poll the isCancelRequested field often enough to
        // react to the cancellation as soon as possible.
        while (!isCancelRequested && ...)
        {
            // ...
        }
    }
}