使用c#中的事件处理程序进行*异常处理

时间:2022-06-14 00:05:06

I am currently asking myself some questions about exception handling and eventhandlers, and i hope some of you will give me some help.

我目前正在问自己一些关于异常处理和事件处理程序的问题,我希望你们中的一些人能给我一些帮助。

I will start to explain what i would like to achieve in my c# application:

我将开始解释我想在c#应用程序中实现的目标:

I have a top-level method (lets call it the main method). This method calls an asynchronous method (wich is called connect), which connect to a FTP server.

我有一个*方法(让我们称之为main方法)。此方法调用连接到FTP服务器的异步方法(称为连接)。

An EventHandler object is associated to this connection, and a "callback" method is called when the connection is successful.

EventHandler对象与此连接相关联,并且在连接成功时调用“callback”方法。

I want to handle exceptions that can be launched during the whole process. So i would like to catch it in the top level method. It works fine for exceptions launched by the connect method (which is called inside the top level method). However, it does not work for exceptions called inside the "callback" method: the top level method does not catch them and the execution fails.

我想处理可以在整个过程中启动的异常。所以我想在*方法中捕获它。它适用于connect方法启动的异常(在*方法中调用)。但是,它不适用于“回调”方法内部调用的异常:*方法不捕获它们并且执行失败。

What can I do to make these exceptions beeing caught by the top level method ? I don't want to handle these exceptions in the callback.

我可以做些什么来使*方法捕获这些异常?我不想在回调中处理这些异常。

5 个解决方案

#1


Take a look at how the Backgroundworker deals with this: the Exception is propagated to the Completed event handler.

看看Backgroundworker如何处理这个:Exception传播到Completed事件处理程序。

I assume you have some form of State object that is passed to/from the delegate, that's where you can add such a property. And you will have to catch all exceptions in the thread, at the outermost scope. But 'handling' just means passing it along.

我假设您有一些形式的State对象传递给委托/从委托传递,您可以在这里添加这样的属性。而且你必须在最外层的范围内捕获线程中的所有异常。但“处理”只是意味着传递它。

There is a standard pattern for the RunWorkerCompleted event, see this MSDN page.

RunWorkerCompleted事件有一个标准模式,请参阅此MSDN页面。

#2


Consider the below code fragment for wrapping all of your code in a global exception handler:

考虑以下代码片段,将所有代码包装在全局异常处理程序中:

namespace MyClient
{
  class Program
  {
    static void Main(string[] args)
    {
      try
      {
        bool isSuccess = SubMain(string[] args);
      }
      catch (Exception e)
      {
        HandleExceptionGracefully(e);
      }
    }
    static bool SubMain(string[] agrs)
    {
       // Do something
    }
    static void HandleExceptionGracefully(Exception e)
    {
       // Display/Send the exception in a graceful manner to the user/admin.
    }
  }
}

Also, don't forget to make your error handling user-friendly.

此外,不要忘记让您的错误处理用户友好。

#3


There is an event handler in the Application class called ThreadException. This event will be fired whenever an exception is thrown an not caught anywhere in the current call stack.

Application类中有一个名为ThreadException的事件处理程序。每当抛出一个未捕获当前调用堆栈中的任何异常时,将触发此事件。


Edited:

Sorry, I misread the question - I didn't realise that the "main" method in your example isn't the actual main method. In that case you may want to catch the exception inside the callback, but not handle it - instead simply pass it back up to the main method as part of the event args.

对不起,我误解了这个问题 - 我没有意识到你的例子中的“主要”方法不是实际的主要方法。在这种情况下,您可能希望在回调中捕获异常,但不处理它 - 而只是将其作为事件args的一部分传递回main方法。

The BackgroundWorker in Winforms does something similar.

Winforms中的BackgroundWorker做了类似的事情。

#4


Thanks for your answers.

谢谢你的回答。

It seems that using the BackgroundWorker solve this problem.

似乎使用BackgroundWorker解决了这个问题。

I did not try it, because i chose to avoid this implementation burden. So I took away my asynchronous call and made my application behaving synchronously.

我没有尝试过,因为我选择避免这种实施负担。所以我带走了异步调用并使我的应用程序同步运行。

One tip for people using the Compact Framework instead of the full .NET Framework: the BackgroundWorker is not available in CF, but a similar solution is provided by OpenNETCF (see the BackgroundWorker class in the Smart Device Framework).

使用Compact Framework而不是完整.NET Framework的人的一个提示:背景工作在CF中不可用,但OpenNETCF提供了类似的解决方案(请参阅智能设备框架中的BackgroundWorker类)。

#5


A more convenient way to deal with this problem of top-level exception handling is to use delegates.

处理*异常处理问题的一种更方便的方法是使用委托。

These c# delegates allow to call methods in a asynchronous way. And delegates allow also top-level exception handling. Indeed, exceptions thrown inside delegates are re-thrown on the original thread.

这些c#委托允许以异步方式调用方法。代表也允许*异常处理。实际上,在委托中抛出的异常会重新抛出原始线程。

I don't know why i did not think about delegates before. I hope it will help.

我不知道为什么我之前没有考虑过代表。我希望它会有所帮助。

See these nice articles about delegates:

请参阅这些关于委托的好文章:

Article 1

Article 2

#1


Take a look at how the Backgroundworker deals with this: the Exception is propagated to the Completed event handler.

看看Backgroundworker如何处理这个:Exception传播到Completed事件处理程序。

I assume you have some form of State object that is passed to/from the delegate, that's where you can add such a property. And you will have to catch all exceptions in the thread, at the outermost scope. But 'handling' just means passing it along.

我假设您有一些形式的State对象传递给委托/从委托传递,您可以在这里添加这样的属性。而且你必须在最外层的范围内捕获线程中的所有异常。但“处理”只是意味着传递它。

There is a standard pattern for the RunWorkerCompleted event, see this MSDN page.

RunWorkerCompleted事件有一个标准模式,请参阅此MSDN页面。

#2


Consider the below code fragment for wrapping all of your code in a global exception handler:

考虑以下代码片段,将所有代码包装在全局异常处理程序中:

namespace MyClient
{
  class Program
  {
    static void Main(string[] args)
    {
      try
      {
        bool isSuccess = SubMain(string[] args);
      }
      catch (Exception e)
      {
        HandleExceptionGracefully(e);
      }
    }
    static bool SubMain(string[] agrs)
    {
       // Do something
    }
    static void HandleExceptionGracefully(Exception e)
    {
       // Display/Send the exception in a graceful manner to the user/admin.
    }
  }
}

Also, don't forget to make your error handling user-friendly.

此外,不要忘记让您的错误处理用户友好。

#3


There is an event handler in the Application class called ThreadException. This event will be fired whenever an exception is thrown an not caught anywhere in the current call stack.

Application类中有一个名为ThreadException的事件处理程序。每当抛出一个未捕获当前调用堆栈中的任何异常时,将触发此事件。


Edited:

Sorry, I misread the question - I didn't realise that the "main" method in your example isn't the actual main method. In that case you may want to catch the exception inside the callback, but not handle it - instead simply pass it back up to the main method as part of the event args.

对不起,我误解了这个问题 - 我没有意识到你的例子中的“主要”方法不是实际的主要方法。在这种情况下,您可能希望在回调中捕获异常,但不处理它 - 而只是将其作为事件args的一部分传递回main方法。

The BackgroundWorker in Winforms does something similar.

Winforms中的BackgroundWorker做了类似的事情。

#4


Thanks for your answers.

谢谢你的回答。

It seems that using the BackgroundWorker solve this problem.

似乎使用BackgroundWorker解决了这个问题。

I did not try it, because i chose to avoid this implementation burden. So I took away my asynchronous call and made my application behaving synchronously.

我没有尝试过,因为我选择避免这种实施负担。所以我带走了异步调用并使我的应用程序同步运行。

One tip for people using the Compact Framework instead of the full .NET Framework: the BackgroundWorker is not available in CF, but a similar solution is provided by OpenNETCF (see the BackgroundWorker class in the Smart Device Framework).

使用Compact Framework而不是完整.NET Framework的人的一个提示:背景工作在CF中不可用,但OpenNETCF提供了类似的解决方案(请参阅智能设备框架中的BackgroundWorker类)。

#5


A more convenient way to deal with this problem of top-level exception handling is to use delegates.

处理*异常处理问题的一种更方便的方法是使用委托。

These c# delegates allow to call methods in a asynchronous way. And delegates allow also top-level exception handling. Indeed, exceptions thrown inside delegates are re-thrown on the original thread.

这些c#委托允许以异步方式调用方法。代表也允许*异常处理。实际上,在委托中抛出的异常会重新抛出原始线程。

I don't know why i did not think about delegates before. I hope it will help.

我不知道为什么我之前没有考虑过代表。我希望它会有所帮助。

See these nice articles about delegates:

请参阅这些关于委托的好文章:

Article 1

Article 2