【发布时间】:2012-10-24 22:59:28
【问题描述】:
我有一个BackgroundWorker,它调用一个调用一个方法的方法......在某处我检查CancellationPending并想退出BackgroundWorker。
有没有办法直接从那个深度嵌套的方法中做到这一点,还是必须返回给它的调用者,而后者又会返回给它的调用者......?
【问题讨论】:
标签: c# winforms backgroundworker
我有一个BackgroundWorker,它调用一个调用一个方法的方法......在某处我检查CancellationPending并想退出BackgroundWorker。
有没有办法直接从那个深度嵌套的方法中做到这一点,还是必须返回给它的调用者,而后者又会返回给它的调用者......?
【问题讨论】:
标签: c# winforms backgroundworker
您使用BackgroundWorker这一事实并没有什么特别之处 - 请按照与处理深度嵌套方法调用相同的术语来考虑这一点。
换句话说,不,我想不出(不可怕的)方法可以直接做到这一点。
我能想到的最简洁的方法是在从每个嵌套方法返回后立即在每个级别检查CancellationPending(如果true,则返回)。
在顶层抛出特定异常并捕获相同的特定异常类型可以让您快速退出,但这并不是最佳实践(也就是说,不要使用任何非异常的异常,例如正常的流控制)。
【讨论】:
调用方法的BackgroundWorker调用方法...
有没有办法直接从那个深度嵌套的方法中[取消]
你可以抛出一个异常。但这与仅对错误使用异常的一般建议相提并论。
【讨论】:
有很多方法,我更喜欢这个实现,虽然它限制了一点参数,但你可以改变它。要点是您将引用作为参数传递给BackgroudWorker:
bkgw = new BackgroundWorker();
bkgw.DoWork += new DoWorkEventHandler(bkgw_DoWork);
bkgw.WorkerSupportsCancellation = true;
void bkgw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker b = (BackgroundWorker)sender;
if (b.CancellationPending)
{
e.Cancel = true;
return;
}
if (!Method1(b))
{
e.Cancel = true;
return;
}
if (b.CancellationPending)
{
e.Cancel = true;
return;
}
}
bool Method1(BackgroundWorker caller)
{
//some code
if (caller.CancellationPending)
return false;
if (!Method2(caller))
return false;
//some code
return true;
}
bool Method2(BackgroundWorker caller)
{
//some code
if (caller.CancellationPending)
return false;
//some code
return true;
}
【讨论】:
你可以,但你不应该。
除了其他答案中提到的抛出异常之外,没有人敢说的邪恶是Thread.Abort()。如果您从在 BackgroundWorker 线程上执行的函数中调用它,则整个线程将退出。 Thread.Abort() 的弊端已被详细讨论elsewhere on this site。
话虽如此,正确的做法是构建你的代码,以便当一个深度嵌套的函数决定线程应该退出时,这个意图被传播到堆栈中的主线程方法,然后可以退出干净利落
【讨论】:
Thread.Abort的大部分问题都是直接从另一个线程调用的结果,所以你不知道异常会从哪里抛出。它可以从阻塞 IO 调用的中间抛出,在 finally 块或 catch 块中,它可能被线程捕获和吞噬,等等。