将异常从 BackgroundWorker 传递给调用方类

Passing the exception from BackgroundWorker to the caller class

提问人:EmeraldP 提问时间:10/28/2023 更新时间:10/28/2023 访问量:82

问:

处理 BackgroundWorker 中发生的异常的正确方法是通过 RunWorkerCompleted 事件中 args 的 Error 属性进行处理。从那里您可以显示用户消息。

但是,我正在努力添加一个不确定的进度微调器,以便在执行现有代码段时显示。需要明确的是 - 然后应该阻止 UI,但为了视觉效果,我们需要一个微调器。因此,我决定使用 BackgroundWorker 来完成这项工作,以便微调器可以在 UI 线程上运行。

我遇到的问题是现有代码(下面的 Run() 方法)在现有的 try-catch 块中执行,该块包含一个非常重要的回滚,以防出现异常。

我开始想知道是否可以使用 RunWorkerCompleted 将异常分配给容器类的属性,稍后在代码中检查是否已分配此类异常并抛出它(如下图所示)。

为了确保 RunWorkerCompleted 将在方法进一步执行之前执行,我将关闭进度微调器的调用放在 RunWorkerCompleted 中,而不是 DoWork 的末尾。

public class MyClass
{
    Exception bgWorkerException = null;
    int someProperty = 0;

    public int Run(){
        using (AutoResetEvent rEvent = new AutoResetEvent(false)){
            BackgroundWorker bgWorker = new BackgroundWorker();

            bgWorker.DoWork += new DoWorkEventHandler((sender, e) => {
                try {
                    // The actual code that we want to execute
                    // Do the work, set someProperty value and possibly throw an exception
                }
                finally {
                    rEvent.Set();
                }
            }

            bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler((sender, e) => {
                if (e.Error != null)
                    bgWorkerException = e.Error;
                progress.Completed = true; // raises the progressBar property changed to invoke the close command
            }

            bgWorker.RunWorkerAsync();
            ShowProgressBar(); // displays it and blocks further execution until progress.Completed is set to true
            if (!progress.Completed)
                rEvent.WaitOne();
        }

        if (bgWorkerException != null)
            throw bgWorkerException;

        return someProperty;
    }
}

我的问题是:这种方法有什么风险吗?RunWorkerCompleted 会一直执行吗?根据我的基本测试,它似乎按预期工作。

C# WPF 异常 BackgroundWorker 调度程序

评论

1赞 Fildor 10/28/2023
报废并与之一起使用async TaskIProgress<T>
1赞 Clemens 10/28/2023
BackgroundWorker 已过时。您只需致电var someProperty = await Task.Run(() => { /* do something and return value */ });
0赞 EmeraldP 10/29/2023
@Clemens 然后我在非异步调用程序中返回 someProperty.Result?似乎也有效。关于bgWorker,我确实意识到它已经过时了,但从技术上讲,这种方法安全吗?
0赞 Servy 10/29/2023
如果您要同步等待工作完成,那么首先使用后台工作线程是没有意义的。与其创建一个新的工作线程来做工作,而你强迫线程坐在那里什么都不做,不如做工作。
0赞 Clemens 10/29/2023
您不返回 Task.Result,而只返回等待的 Task 的返回值,即一个值。int

答: 暂无答案