gpt4 book ai didi

multithreading - BackgroundWorker 中的异步错误处理

转载 作者:行者123 更新时间:2023-12-03 13:05:10 25 4
gpt4 key购买 nike

如何获得有意义的BackgroundWorker.ErrorDoWork必须调用可能引发异常的委托(delegate)?

我正在实现一个静态 MsgBox公开向用户传达自定义消息的各种方式(使用自定义消息表单)的类。

公开的方法之一,ShowProgress , 实例化一个 ProgressMessageBoxForm (源自自定义 MessageBoxForm ),它在某些后台操作发生时显示进度条(让用户一直取消操作)。如果在模态表单上运行后台任务听起来很尴尬,请考虑这样的签名:

public static DialogResult ShowProgress(string title, string message, _
Action<AsyncProgressArgs> progressAction)

这个想法是封装一个后台工作人员,将其“工作”委托(delegate)给任何提供的方法(/处理程序),同时允许该方法“对话”并报告进度和取消......以及理想情况下的错误状态。在这种情况下,表单是否是模态的,在可取消的模态表单上的进度条中显示正在运行的任务的进度的能力,除非取消选中复选框以保持可见和显示,否则该表单也会自动关闭完成后的成功状态是必需的功能。

这是 AsyncProgressArgs有问题的类(class):
public class AsyncProgressArgs
{
private readonly Action<int, string> _update;
private readonly BackgroundWorker _worker;
private readonly DoWorkEventArgs _workEventArgs;

public AsyncProgressArgs(Action<int, string> updateProgress, BackgroundWorker worker, DoWorkEventArgs e)
{
_update = updateProgress;
_worker = worker;
_workEventArgs = e;
}

/// <summary>
/// Reports progress to underlying <see cref="BackgroundWorker"/>.
/// Increments <see cref="ProgressBar"/> value by specified <see cref="int"/> amount and
/// updates the progress <see cref="Label"/> with specified <see cref="string"/> caption.
/// </summary>
public Action<int, string> UpdateProgress { get { return _update; } }

/// <summary>
/// Verifies whether asynchronous action is pending cancellation,
/// in which case asynchronous operation gets cancelled.
/// </summary>
public void CheckCancelled()
{
_workEventArgs.Cancel = _worker.CancellationPending;
}
}
BackgroundWorkerDoWork事件处理程序然后调用传递给自定义消息框的方法
protected virtual void worker_DoWork(object sender, DoWorkEventArgs e)
{
// *** If RunWorkerCompletedEventArgs.Error caught exceptions,
// then this try/catch block wouldn't be needed:
// try
// {
_startHandler(this, new AsyncProgressArgs(UpdateProgressAsync, _worker, e));
// }
// catch(Exception exception)
// {
// if (MsgBox.Show(exception) == DialogResult.Retry)
// {
// BeginWork(_startHandler);
// }
// else
// {
// Hide();
// }
// }
}

给定这样的方法:
private void AsyncProgressAction(AsyncProgressArgs e)
{
// do some work:
Thread.Sleep(200);

// increment progress bar value and change status message:
e.UpdateProgress(10, "Operation #1 completed.");

// see if cancellation was requested:
e.CheckCancelled();


// do some work:
Thread.Sleep(500);

// increment progress bar value and change status message:
e.UpdateProgress(30, "Operation #2 completed.");

// see if cancellation was requested:
e.CheckCancelled();

// ...

// throw new Exception("This should be caught by the BackgroundWorker");
}

调用代码可能如下所示:
MsgBox.ShowProgress("Async Test", "Please wait while operation completes.", _
AsyncProgressAction);

一切都按预期工作(进度条移动,可以取消该过程),直到在操作方法中引发异常。通常是 BackgroundWorker将捕获它并将其存储在其 Error 中属性(property),但这里不会发生。

因此,传递的操作方法中的代码需要处理它自己的异常,如果不处理,它就会保持未处理状态,并且程序会以可怕的方式死亡。

问题是,是否有可能拥有这样的构造,并且仍然能够以某种方式拥有有意义的 Error过程完成时的属性(property)?我希望能够 Throw new Exception()在 action 方法中的任何地方,并在封装的 worker 中处理它。

旁注,我求助于 BackgroundWorker因为与 Task在完成所有工作之前我无法移动进度条,我想避免处理 Thread直接对象实例。

编辑
这不是问题,编译后的应用程序不会崩溃。实际上,我对调试器中断委托(delegate)方法中抛出的异常感到困惑。正如下面的评论中所指出的,执行/调试可以在之后继续,并且任何打算运行的错误处理逻辑都会运行。我期待 BackgroundWorker以某种方式 catch异常和调试器继续运行,但事实证明异常被捕获并且调试器仍然中断。

我之前应该读过这个: Unhandled exceptions in BackgroundWorker

最佳答案

我之前应该读过这个: Unhandled exceptions in BackgroundWorker

这是一个非常非常长的问题,对于一个简单的非问题有很多上下文:VS调试器停止并误导性地说“用户代码未处理异常”,就像未处理的异常一样......当它实际上意味着“BackgroundWorker 任务引发了异常,调试器会通知您,否则您会认为 BackgroundWorker 正在吞噬它。”

异常可以 F5'd/忽略以恢复执行,异常确实如预期的那样以 RunWorkerCompletedEventArgs.Error 结束,并且部署的应用程序不会在用户面前爆炸。

发布此答案以从(溢出?)一堆未回答的问题中删除此问题...

关于multithreading - BackgroundWorker 中的异步错误处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14791603/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com