如何取消backgroundworker并将IsBusy设置为false?

问题描述 投票:0回答:2

我用

RunWorkerAsync()
在 WinForms 中启动了后台工作者。该工作人员运行状态机并执行一些工作。我在表单上有一个“取消”按钮,该按钮应该停止工作人员;我用
CancelAsync()
来做这个。

问题是,我使用属性

IsBusy
在启动之前检查后台工作程序是否正在运行,但是,当调用
CancelAsync()
时,此属性仍然是
true
。因此,当我尝试重新启动工作程序时,它不会启动,因为逻辑认为它仍在运行。

在启动工作程序后,我尝试在 while 循环中使用

Application.DoEvents()
来保持表单响应,但这并没有解决问题。

我还尝试将

IsBusy
属性明确设置为 false,但据我了解,该属性是只读的。

据我目前的理解,只有在后台工作程序完成其操作后,

IsBusy
才会设置为 false,这意味着使用
CancelAsync()
不会将该属性设置为 false,因为从技术上讲,它并没有完成工作程序的操作。

有解决方法吗?还是我理解错误?

private void buttonStart_Click(object sender, EventArgs e)
{
    if (!backgroundWorker1.IsBusy)
    {
        backgroundWorker1.RunWorkerAsync();
        buttonStart.Enabled = false;
    }
}

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    BackgroundWorker worker = (BackgroundWorker)sender;

    while (!worker.CancellationPending)
    {
        ...
    }
}

private void buttonCancel_Click(object sender, EventArgs e)
{
    if (backgroundWorker1.WorkerSupportsCancellation && backgroundWorker1.IsBusy)
    {
        backgroundWorker1.CancelAsync();
        buttonStart.Enabled = true;
    }
}
c# winforms backgroundworker
2个回答
0
投票

BackgroundWorker
有一个
CancellationPending
属性
,顾名思义,如果通过调用
true
方法发出取消信号,则返回
CancelAsync
。您可以将此属性与
IsBusy
结合使用来实现您想要的。


0
投票

据我目前的理解,一旦后台工作者完成其操作,IsBusy 才会被设置为 false...

这是正确的。调用

CancelAsync()
本身不会将
IsBusy
设置为 false,这只能在工作进程完成其进程后才能完成。工作人员的完成被定义为
_DoWork()
函数到达终点。

因此,要取消该工作人员,我们只需在

e.cancel
时将
CancellationPending
设置为 true 即可。为此,需要更改
_DoWork()
函数中的逻辑。首先,需要更改
while
循环的条件,以便检查
CancellationPending

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    BackgroundWorker worker = (BackgroundWorker)sender;

    while (someCondition)
    {
        if (worker.CancellationPending)
        {
            e.Cancel = true;
            break;
        }

        ...
    }
}

通过调用

break
,应用程序退出主 while 循环,从而完成
_DoWork
函数。

© www.soinside.com 2019 - 2024. All rights reserved.