簡體   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