我想中止该过程但不能这样做,我正在使用后台工作者处理我的功能。
public void Init()
{
bw = new BackgroundWorker();
bw.WorkerSupportsCancellation = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
if (bw.CancellationPending == true)
{
e.Cancel = true;
}
else
{
e.Result = abd();
}
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(e.Cancelled)
{
lbltext.content="Canceled";
}
else
{
lbltext.content="Completed";
}
}
private void btncan_Click(object sender, RoutedEventArgs e)
{
bw.CancelAsync();
}
private void btnstart_Click(object sender, RoutedEventArgs e)
{
bw.RunWorkerAsync();
}
我无法使用此代码中止该过程。
函数abd()
正在执行处理部分并返回结果。
请给我任何解决方案。
感谢。
答案 0 :(得分:12)
当您致电bw.CancelAsync()
时,您只需将CancellationPending
标记设为true
即可。默认情况下它不会取消某些内容。您需要手动处理待处理的取消。但是你不能用你的代码做到这一点,因为当你点击按钮时,有三种可能的选择:
abd()
方法完成了它的工作,没有什么可以取消abd()
启动它的工作,后台工作程序被阻止 - 它等待abd()
的结果,然后继续执行 - 即退出if-else
阻止并引发RunWorkerCompleted
事件if-else
块之前单击按钮。比CancellationPending
为真,abd()
不会开始执行如果您想使用取消,请在循环中执行长时间运行的任务,并检查每个步骤是否有待取消:
void bw_DoWork(object sender, DoWorkEventArgs e)
{
List<Foo> results = new List<Foo>();
// any loop here - foreach, while
for(int i = 0; i < steps_count; i++)
{
// check status on each step
if (bw.CancellationPending == true)
{
e.Cancel = true;
return; // abort work, if it's cancelled
}
results.Add(abd()); // add part of results
}
e.Result = results; // return all results
}
答案 1 :(得分:1)
可能DoWork
在调用CancelAsync
之前可能已完成其工作,并且如文档e.Cancelled
中所述可能是错误的。
Docs说这个
请注意,DoWork事件处理程序中的代码可能会完成 正在进行取消请求,以及您的轮询循环 可能会错过CancellationPending设置为true。在这种情况下, 取消了System.ComponentModel.RunWorkerCompletedEventArgs中的标志 即使您的RunWorkerCompleted事件处理程序也不会设置为true 虽然取消了请求。这种情况称为a 竞争条件,是多线程编程中常见的问题。
答案 2 :(得分:0)
以下情况如何?
While(!bw.CancellationPending)
{
//do some work!
}
e.Cancel = true;
答案 3 :(得分:0)
函数abd()
占用的处理时间过多,您想在两者之间中止处理。
private Thread _backgroundWorkerThread;
public void AbortBackgroundWorker()
{
if(_backgroundWorkerThread != null)
_backgroundWorkerThread.Abort();
}
void DoWork(object sender, DoWorkEventArgs e)
{
try
{
_backgroundWorkerThread = Thread.CurrentThread;
// call abd...
}
catch(ThreadAbortException)
{
// Do your clean up here.
}
}
将AbortBackgroundWorker()
放入btncan_Click
事件中。
但这要付出代价。现在,RunWorkerCompleted事件将不起作用。因此,您将不得不在catch块中处理它或编写我们自己的代码。