C#从委托.begininvoke捕获异常而不调用委托.endinvoke

时间:2020-01-20 19:25:54

标签: c# multithreading exception delegates

我有一个监视数据库(或多个数据库)的程序。 为此,我建立了一个类,其中包含有关如何监视数据库的所有信息。 该类包含一个委托,该委托指向一个监视数据库的函数,并相应地更改状态字段。

主线程创建该类的新实例并调用class.delegate.begininvoke()。 主线程会循环检查每个已创建类的状态,并在发生任何更改时通知用户。

简单的代码示例:

netsh winhttp reset proxy 

我遇到的问题是异常处理,如果MonitorHandler函数抛出异常,我没有办法知道它。

我不调用EndInvoke,因此不会将异常重新引发到主线程中。

我的目标是通过简单地破解监视器实例的状态字段来检查数据库状态。 如果引发了异常,我需要以某种方式将该异常“转移”到主线程,但是我不想开始检查状态和Monitor委托状态。

我真想找到一种方法来监视线程本身(由.BeginInvoke激活的方法),以将异常抛出到主线程中。

谢谢。

1 个答案:

答案 0 :(得分:2)

我真想找到一种方法来监视线程本身(由.BeginInvoke激活的方法),以将异常抛出到主线程中。

除了ThreadAbortException之类的东西之外,没有其他机制可以将异常注入到另一个任意线程中。

如果要使用委托的BeginInvoke()方法,并且想在与调用委托本身不同的线程中捕获异常,那么您将需要在其中调用EndInvoke()该线程。

您的另一个选择是显式地手动处理异常。即使用工作线程中的try / catch捕获异常,然后使用自己选择的显式定义的机制(例如ConcurrentQueue<T>)将捕获的异常传递给在主线程。

所有这些,使用委托人的BeginInvoke()方法从来都不是那种理想的异步执行代码的理想方法,而今天,这种想法更糟了。从您的问题尚不清楚“主线程”的本质是什么,不要管该线程是否具有同步上下文。但是假设它确实起作用(例如,它是GUI线程或ASP.NET上下文等),则可以使用Task.Run()来启动异步操作,然后在{主线程来捕获该操作的完成以及抛出的任何异常。

为此,即使您的主线程当前没有同步上下文,也可能给它一个正确的方法。通过利用现有机制之一,或编写自己的机制。例如,如果您希望经常在代码中遇到这种“将异常从工作程序传播到主线程”的情况,那么这将是一个好主意。这样一来,您就可以使用内置的语言支持来处理该问题(即await / async),而不必为每个实例都花点时间。实现同步上下文并不是一件容易的事,但是您可以一次完成工作,然后一遍又一遍地重复使用。