需要帮助停止BackgroundWorker线程

8

需要帮助停止BackgroundWorker线程。

我正在尝试停止一个BackgroundWorker线程。以下是我的操作:

在停止按钮点击事件中(UI层):

if (backgroundWorker.IsBusy == true && 
    backgroundWorker.WorkerSupportsCancellation == true)
{
    backgroundWorker.CancelAsync();
}

在DoWork事件(UI层)中:

if ((backgroundWorker.CancellationPending == true))
{
     e.Cancel = true;
}
else
{
    //Function which progresses the progress bar is called 
    //here with its definition in business layer 
}

一旦DoWork事件被触发并且我的程序控制在业务层定义的函数中,我该如何返回到DoWork事件以设置 'e.Cancel = true'?

5个回答

3

如果CancellationPending为true,那么设置e.Cancel是无效的,你需要使用return或其他方法(在停止正在进行的操作后)从DoWork()中跳出。

类似于以下代码:

private void DoWork(...)
{
    // An infinite loop of work!
    while (true) 
    {
        // If set to cancel, break the loop
        if (worker.CancellationPending) 
            break;

        // Sleep for a bit (do work)
        Thread.Sleep(100);
    }
}

DoWork() 在一个单独的线程中执行,您可以使用 BackgroundWorker.ReportProgress() 将结果反馈给 UI 线程。


2

DoWork 将在它自己的线程中运行,不依赖于GUI线程。

你几乎做得没错。从GUI线程中,将 CancellationPending 设置为 true

DoWork 方法中,你可能有一个循环。

在这里,你可以检查 CancellationPending == true,但是除了设置 e.Cancel 为true之外,还需要包含一个 return 调用来使该方法返回并有效地停止工作。如果该方法已连接到GUI线程,则这也会导致WorkerCompleted事件在GUI线程上触发。

如果 DoWork 方法执行的是没有分成部分的长时间任务(例如,如果你的 DoWork 方法看起来像这样:

void DoWork( (object sender, DoWorkEventArgs e)
{
   myClass.SomeLongOperation();
}

如果你需要手动检查 CancellationPending 来停止程序,那么你可能会运气不佳。如果 DoWork 方法本身 "挂起" 并等待你无法控制的操作,你将无法通过从 GUI 线程设置 CancellationPending 来有序地停止它。


1
如果在DoWork中没有循环,那么它是不会工作的。 - stuartd
1
@Stuart - 正确,正如答案中所提到的。如果没有循环,没有好的方法在不强制从GUI线程杀死线程的情况下关闭它。 - Øyvind Bråthen
@Øyvind Knobloch-Bråthen - 请告诉我从GUI线程强制终止Backgroundworker线程的错误方法(不使用DoWork中的循环)。 - Zeeshanef
@Zeeshanef - 这将涉及从线程池中找到正确的线程(应该可以通过某种方式实现,但我不知道如何),并使用Thread.Abort方法手动中止它。我自己从未尝试过,希望我永远也不必这样做 ;) - Øyvind Bråthen

2
一旦触发DoWork事件并且程序控制权在业务层中定义的函数内部时,如何返回到DoWork事件以设置“e.Cancel = true”?
你不能这样做。如果您希望在执行业务层期间可以取消,则您的业务层必须支持取消。因此,您有两个选择:
1. 在DoWork方法中,仅调用短时间的业务层方法,并在它们之间检查CancellationPending。
2. 使您的业务层方法支持取消,即将BackgroundWorker传递给它们,并定期检查CancellationPending(一旦它变为true,就会返回)。

0
代码e.Cancel = true只是在BackgroundWorker上设置一个状态,以便它知道已被取消,而并不实际取消进程。
您必须在方法循环中检查CancellationPendingbreakreturn
void DoWork(object sender, DoWorkEventArgs e) {
    for (int i = 0; i < length; i++) {
        if(e.CancellationPending) {
            return;
        }
        // Long running code
    }
}

0
在逻辑的else部分不断检查CancellationPending=True标志,当为真时返回。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接