使用异常作为中断/导航.这是个坏主意吗
本文关键字:导航 异常 中断 | 更新日期: 2023-09-27 18:31:40
我正在开发一个基本的Windows窗体应用程序,该应用程序具有一些执行"繁重"工作的功能。因此,我在后台工作线程的帮助下一起使用 ThreadAbortExceptions - 如下所示:
public class AbortableBackgroundWorker : BackgroundWorker
-取消执行功能。我们称这些函数为"HeavyFunction()"
但是,现在 ThreadAbortException 已被捕获在 HeavyFunction() 中,我需要以某种方式回到称为 HeavyFunction() 的"MainForm.cs"类。这是为了确保我正确关闭其他打开的连接(例如编写器)并向用户显示消息。所以,我只是从 HeavyFunction() 中抛出一个异常,然后在 MainForm 中捕获它,就像这样(这是在 HeavyFunction() 中):
catch (ThreadAbortException tae)
{
//Deligate abortion upwards.
SomeWriter.DeleteAndClose();
throw new ArgumentException("relevant message or identifier for later use here");
//close and delete
}
抛出的异常随后在 MainForm 中的"DoWork"函数中捕获,并相应地进行处理。
我的问题 - 这是一种不好的做法吗?
我对Threads和Thread.Abort不太满意(因此首先是后台工作者)
子问题 - 有哪些简单优雅的解决方案可以将响应从调用类中冒泡回表单?
这是一种不好的做法吗?
是的,ThreadAbortException
通常是一种不好的做法。
IMO,如果 MS 从未发明过这个例外,那就更好了,因为许多人认为TAE
是停止任何操作的合法方式。
所以,我只是从 HeavyFunction()
中抛出一个异常 有哪些简单优雅的解决方案可以回泡响应
你刚刚重新发明了TPL的OperationCancelledException
。
简单而优雅的解决方案是使用 TPL 及其优雅的取消模式:
var cts = new CancellationTokenSource();
Task
.Factory
.StartNew(() =>
{
/* HeavyFunction */
while (someCondition)
{
cts.Token.ThrowIfCancellationRequested();
/* do something */
}
}, cts.Token);
如果只想在取消HeavyFunction
时执行某些操作,请在StartNew
后添加延续:
.StartNew(/* */)
.ContinueWith(() => {/* some action */}, TaskContinuationOptions.OnlyOnCanceled);
BackgroundWorker 支持取消方案。
UI 线程必须调用 bw。CancelAsync() 在 DoWork 中,您需要检查 bw。取消待处理属性,如果这是真的,你应该退出DoWork。
private void buttonCancel_Click(object sender, RoutedEventArgs e)
{
if (bw.WorkerSupportsCancellation == true)
{
bw.CancelAsync();
}
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 1; (i <= 10); i++)
{
if ((worker.CancellationPending == true))
{
e.Cancel = true;
break;
}
else
{
// Do something heavy
}
}
}