繁体   English   中英

c# 在不调用 delegate.endinvoke 的情况下从 delegate.begininvoke 捕获异常

[英]c# catch an exception from delegate.begininvoke without calling delegate.endinvoke

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

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

代码的一个简单示例:

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 因此异常不会重新抛出到主线程。

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

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

谢谢你。

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

除了像ThreadAbortException东西之外,没有将异常注入另一个任意线程的机制。

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

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

BeginInvoke() ,使用委托的BeginInvoke()方法从来都不是像这样异步执行代码的理想方式,而今天它甚至是一个更糟糕的想法。 从您的问题中不清楚“主线程”的性质是什么,不管该线程是否具有同步上下文。 但是假设确实如此(例如,它是一个 GUI 线程,或一个 ASP.NET 上下文等),那么您可以使用Task.Run()轻松实现所需的行为来启动异步操作,然后在主线程中使用await来捕获该操作的完成,以及抛出的任何异常。

就此而言,即使您的主线程当前没有同步上下文,给它一个可能是正确的方法。 通过利用现有机制之一,或编写自己的机制。 例如,如果您希望在代码中经常遇到这种“将异常从工作线程传播到主线程”场景,这将是一个好主意。 这将允许您使用内置语言支持来处理(即async / await ),而不必为每个实例编写一些东西。 实现同步上下文并非微不足道,但它是您可以一次完成的工作,然后可以一遍又一遍地重用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM