0

我正在开发一个基本的 Windows 窗体应用程序,该应用程序具有一些执行“繁重”工作的功能。因此,我在后台工作人员的帮助下使用 ThreadAbortExceptions - 如下所示:

public class AbortableBackgroundWorker : BackgroundWorker

-取消正在执行的功能。我们称这些函数为“HeavyFunction()”

但是,既然 ThreadAbortException 已在 HeavyFunction() 中捕获,我不知何故需要回到调用 HeavyFunction() 的“MainForm.cs”类。这是为了确保我正确关闭其他打开的连接(例如 Writer)并向用户显示消息。所以,我只是从 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 不太满意(因此首先是后台工作人员)

子问题- 有哪些简单优雅的解决方案可以将响应从被调用的类中冒泡回表单?

4

2 回答 2

1

这是一个不好的做法吗?

是的,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);
于 2013-09-17T10:43:54.123 回答
0

BackgroundWorker 支持取消场景。

UI 线程必须调用 bw.CancelAsync() 而在 DoWork 中您需要检查 bw.CancellationPending 属性,如果是真的,您应该退出 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
    }
}
}
于 2013-09-17T10:48:41.723 回答