一个简单的代码示例:

问题描述 投票:0回答:1
Class Monitor { private Object lockObj; private delegate void MonitorHandlerDelegate(); private MonitorHandlerDelegate mainHandler; private int State; private int DBid; public Monitor(int DBid) { this.DBid = DBid; mainHandler += MonitorHandler; lockObj = new Object(); } private void MonitorHandler() { do { state = CheckDB(DBid); // 0 is ok, 1 is fail, 2 is InWork, 3 is stop monitoring } while (state != 3); } public int state { get { lock(lockObj) { return State;} } set { lock(lockObj) {State = value;} } } public void Start() { this.state = 0; this.mainHandler.BeginInvoke(null, null); } } public Main() { Monitor firstMonitor = new Monitor(20); firstMonitor.Start(); do { if(firstMonitor.state == 1) WriteLine("DB 20 stop working"); } while(true); }

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

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

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

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

谢谢。

我有一个监视数据库(或多个数据库)的程序。为此,我建立了一个类,其中包含有关如何监视数据库的所有信息。该类包含一个指向函数的委托...

c# multithreading exception delegates
1个回答
0
投票
如果要使用委托的ThreadAbortException方法,并且想要在与调用委托本身不同的线程中捕获异常,那么您将需要在该线程中调用BeginInvoke()
您的另一种选择是显式地手动处理异常。即在工作线程中使用EndInvoke() / try捕获异常,然后使用自己选择的显式定义的机制(例如catch)将捕获的异常传递给在主线程中运行的代码。

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

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

© www.soinside.com 2019 - 2024. All rights reserved.