【问题标题】:c# try...catch statement doesn't capture exception when exception occurred in asynchronous operationc# try...catch 语句在异步操作中发生异常时不捕获异常
【发布时间】:2023-03-10 07:47:01
【问题描述】:

例如:

第一步:绑定UnhandledException事件。

AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

第二步:

try
    {
       //at here,do asynchronous operation and throw a exception.
    }
catch (Exception ex)
   {
            Console.WriteLine("error");
   }

当异步操作抛出异常时,它没有调用catch代码,只是触发了UnhandledException事件,调用end事件后退出应用程序。

我想在 catch 语句中捕获异常并避免退出应用程序。

================================================ ========

异步代码是异步socket操作。在socket异步接收消息事件(BeginReceive,EndReceive)中,我抛出了一个OverFlowException。

throw new OverflowException("chunk size too long.");

==============================================

你是对的,现在我在异步操作中捕获异常并将其传递给原始类(这意味着异常将在同一个线程上抛出,可以尝试...可以调用catcy语句)

【问题讨论】:

  • 如何开始你的异步操作?您应该参考有关用于使操作异步的任何工具的文档。其中一些可能会将异常转发给调用者线程,其中一些可能不会并依赖操作来捕获所有内容,有些(例如:新的async/await 方式)甚至可能吞下异常。

标签: c# exception


【解决方案1】:

默认情况下,异步任务将在与其实例化的上下文不同的上下文中运行。因此在这种情况下,try/catch 块无效。

请按以下方式考虑。

Worker worker = new HouseMaid();
try
{
    worker.DoSomeWork();
}
catch(WorkerIsSickException ex)
{
    worker.TakeMedicin();
    worker.StopWorkingAndRestForAWhile();
}

这里我们看到当worker生病时,工作进程中断并且异常将被处理。但是,当我们这样做时:

Worker worker = new HouseMaid();
try
{
    Worker otherWorker = new HouseMaidHelper();

    worker.DelegateWorkTo(otherWorker, CallBackWhenOTherWorkerIsDone);

    worker.GoOnDoSomethingElse();
}
catch(WorkerIsSickException ex)
{
    worker.TakeMedicin();
    worker.StopWorkingAndRestForAWhile();
}

工作 try/catch 块(或安全网,如果你愿意的话),将只适用于工人,而不是 otherWorker。 otherWorker 有自己的工作范围。如果其他 Worker 失败了,那不应该意味着该 Worker 必须吃药。

【讨论】:

  • 更重要的是,在一般情况下,执行DelegateWorkTo的人可能在HouseMadeHelper遇到任何问题之前已经完成了GoOnDoSomethingElse并完全退出了catch块。在许多模式中,如果调用 WaitForHelperToFinish 方法并且助手已经抛出异常或在完成之前最终抛出异常,WaitForHelperToFinish 方法将表明这一点,通常通过抛出包装助手异常的异常。
  • 如果我错了,请纠正我。在您等待它完成(也称为加入)之前,其他线程中抛出的异常不会传播。然而,未处理的异常事件对我来说是新的,所以我认为在某些情况下它可以或不能捕获其他线程上抛出的异常。可能是因为垃圾收集而在出口处被捕获,它会尝试等待任务完成或中止。
【解决方案2】:

您的问题不清楚,但如果是异步操作引发了异常,那么您展示的代码很容易在引发异常之前完成 - 都是异步的,对吧?

基本上,异步让您重新思考错误处理 - 而您如何处理则取决于您的异步方法。您经常会在回调中捕获异常 - 或者甚至没有捕获它,而是使用 Task.Status 之类的东西来检查它。

诚然,C# 5 中用于异步的所有工作都应该让这部分工作变得更容易,但您仍然需要考虑异步。

【讨论】:

    【解决方案3】:

    异步操作将成功启动,因此执行将继续成功并错过您的异常处理程序。如果要在异步操作中捕获异常,则需要在异步执行的代码中进行异常处理。然后,如果您想在那里处理异常,您可以调用回原始类中的函数。

    【讨论】:

    • 好的,我的理想是异步操作抛出异常,原始类可以通过try...catcy语句捕获它。我只是不想在异步操作中处理异常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-05
    • 1970-01-01
    • 2015-06-21
    • 2011-05-27
    • 1970-01-01
    • 1970-01-01
    • 2012-08-06
    相关资源
    最近更新 更多