C# 委托中的异常处理

C# 委托中的异常处理,c#,exception-handling,delegates,try-catch,msmq,C#,Exception Handling,Delegates,Try Catch,Msmq,我有以下代码,当用户代码试图抛出错误时,它会给我一个“异常未被处理”: private static void _msgQ_RecieveCompleted(object sender, ReceiveCompletedEventArgs e) { try { //queue that have received a message MessageQueue _mq = (MessageQueue)sender; //get th

我有以下代码,当用户代码试图抛出错误时,它会给我一个“异常未被处理”:

private static void _msgQ_RecieveCompleted(object sender, ReceiveCompletedEventArgs e)
{
    try
    {
        //queue that have received a message
        MessageQueue _mq = (MessageQueue)sender;

        //get the message off the queue
        Message _mqmsg = _mq.EndReceive(e.AsyncResult);
        throw new Exception("This is a test exception by Tim");

        //set the values back into a formatted struct 
        //now process your SQL....
        Azure_SQL _azuresql = new Azure_SQL();
        _azuresql.writeMessageToStorage((_TwitterStreamFeed)_mqmsg.Body);

        //refresh queue just in case any changes occurred (optional)
        _mq.Refresh();

        //tell MessageQueue to receive next message when it arrives
        _mq.BeginReceive();

        return;
    }
    catch 
    {
        throw;
    }
}
它由以下方法(以前是代码段)调用:


你能帮我理解为什么错误没有被抛出回
ReceiveCompletedEventHandler
调用吗?我知道它是在不同的线程上执行代码,但我不明白如何从MSDN示例中捕获异常。我希望异常会返回到调用try/catch块。

这里有四种方法

在方法“A”中,例外情况是对所有订户进行多播。这是通过将异常实例作为“innerException”字段包含在自定义EventArgs类中来实现的

在方法“B”中,通过调用单独的委托,“带外”(不是多播,不是事件机制的一部分)处理异常

在方法“C”中,您有一个应用程序级异常处理程序。 您希望通知它,此异常是在处理ReceiveCompleted时发生的。 为此,请定义(并引发)ReceiveCompletedException,它有一个“innerException”字段来包含实际异常

在方法“D”(下面没有给出代码)中,您不关心异常是否发生在ReceiveCompleted代码中。您只需要一个通用的位置来处理异常。这称为“应用程序级异常处理”。看

方法A:

// ========== A: multi-cast "innerException" integrated into EventArgs ==========

public class ReceiveCompletedEventArgs_A
{
    public string myData;   // Set on successful events (no exception).
    public Exception innerException;    // Set when there is an exception.
}

public delegate void ReceiveCompletedEventHandler_A(object sender, ReceiveCompletedEventArgs_A args);

// The Publisher of ReceiveCompleted event, with "innerException" mechanism.
public class RCPublisher_A
{
    public event ReceiveCompletedEventHandler_A ReceiveCompleted;

    public void OnRaiseReceiveCompletedEvent(string myData)
    {
        ReceiveCompletedEventArgs_A rc;
        try
        {
            rc = new ReceiveCompletedEventArgs_A { myData = myData };
            // Uncomment below line, to see an exception being handled.
            //throw new Exception("Testing exception handling");
        }
        catch (Exception ex)
        {
            rc = new ReceiveCompletedEventArgs_A { innerException = ex };
        }

        if (ReceiveCompleted != null)
            ReceiveCompleted(this, rc);
    }
}

// A Subscriber of ReceiveCompleted event, with "innerException" mechanism.
public class RCSubscriber_A
{
    public void Initialize(RCPublisher_A rcp)
    {
        rcp.ReceiveCompleted += OnReceiveCompleted;
    }

    private void OnReceiveCompleted(object sender, ReceiveCompletedEventArgs_A rc)
    {
        if (rc.innerException != null)
        {
            // Handle the exception
        }
        else
        {
            // Use rc.myData
        }
    }
}
方法B:

// ========== B: "Out-of-band" handling of exceptions; not multi-cast ==========
// (Successful events are multi-cast, but exceptions are sent to a single delegate.)

public class ReceiveCompletedEventArgs_B
{
    public string myData;   // Set on successful events (no exception).
}

public delegate void ReceiveCompletedEventHandler_B(object sender, ReceiveCompletedEventArgs_B args);

public delegate void ExceptionDelegate(Exception ex);

// The Publisher of ReceiveCompleted event, with out-of-band Exception handling.
public class RCPublisher_B
{
    // Called when the event is successful (no exception).
    public event ReceiveCompletedEventHandler_B ReceiveCompleted;

    // Called when there is an exception.
    public ExceptionDelegate exceptionDeleg;

    public void OnRaiseReceiveCompletedEvent(string myData)
    {
        try
        {
            ReceiveCompletedEventArgs_B rc = new ReceiveCompletedEventArgs_B { myData = myData };
            // Uncomment below line, to see an exception being handled.
            //throw new Exception("Testing exception handling");

            if (ReceiveCompleted != null)
                ReceiveCompleted(this, rc);
        }
        catch (Exception ex)
        {
            if (exceptionDeleg != null)
                exceptionDeleg(ex);
            // What to do if there is no exceptionDeleg:
            //   If below line is commented out, unhandled exceptions are swallowed.
            //   Uncomment, to throw them to your app-level exception handler.
            else throw;
        }

    }
}

// A Subscriber of ReceiveCompleted event, with out-of-band Exception handling.
public class RCSubscriber_B
{
    public void Initialize(RCPublisher_B rcp)
    {
        rcp.ReceiveCompleted += OnReceiveCompleted;
        // CAUTION: Overrides any other exception delegate.
        // If you need multi-casting of the exception, see Approach A.
        rcp.exceptionDeleg = RCExceptionOccurred;
    }

    private void OnReceiveCompleted(object sender, ReceiveCompletedEventArgs_B rc)
    {
        // Use rc.myData
    }

    private void RCExceptionOccurred(Exception ex)
    {
        // Use ex.
    }
}
方法C:

// ========== C: Wrap "innerException" into custom Exception, for app-level handler ==========
// Similar to B, but instead of adding ExceptionDelegate and exceptionDeleg,
// Define a custom exception type, and throw it.
// Catch it inside your app-level handler.
public class ReceiveCompletedException : Exception 
{
    public Exception innerException;
}

public class RCPublisher_C
{
    public event ReceiveCompletedEventHandler_B ReceiveCompleted;

    public void OnRaiseReceiveCompletedEvent(string myData)
    {
        ReceiveCompletedEventArgs_B rc;
        try
        {
            rc = new ReceiveCompletedEventArgs_B { myData = myData };
            // Uncomment below line, to see an exception being handled.
            //throw new Exception("Testing exception handling");

            if (ReceiveCompleted != null)
                ReceiveCompleted(this, rc);
        }
        catch (Exception ex)
        {
            throw new ReceiveCompletedException{ innerException =  ex };
        }
    }
}

// ...
// In your app-level handler:
        // ...
        catch (ReceiveCompletedException rce)
        {
           // If it gets here, then an exception happened in ReceiveCompleted code.
           // Perhaps you have some graceful way of restarting just that subsystem.
           // Or perhaps you want a more accurate log, that instead of just saying
           // "Exception XYZ happened" (the inner exception), logs that it was
           // ReceiveCompleted that has the problem.
           // use rce.innerException
        }
        // ...

这里有四种方法

在方法“A”中,例外情况是对所有订户进行多播。这是通过将异常实例作为“innerException”字段包含在自定义EventArgs类中来实现的

在方法“B”中,通过调用单独的委托,“带外”(不是多播,不是事件机制的一部分)处理异常

在方法“C”中,您有一个应用程序级异常处理程序。 您希望通知它,此异常是在处理ReceiveCompleted时发生的。 为此,请定义(并引发)ReceiveCompletedException,它有一个“innerException”字段来包含实际异常

在方法“D”(下面没有给出代码)中,您不关心异常是否发生在ReceiveCompleted代码中。您只需要一个通用的位置来处理异常。这称为“应用程序级异常处理”。看

方法A:

// ========== A: multi-cast "innerException" integrated into EventArgs ==========

public class ReceiveCompletedEventArgs_A
{
    public string myData;   // Set on successful events (no exception).
    public Exception innerException;    // Set when there is an exception.
}

public delegate void ReceiveCompletedEventHandler_A(object sender, ReceiveCompletedEventArgs_A args);

// The Publisher of ReceiveCompleted event, with "innerException" mechanism.
public class RCPublisher_A
{
    public event ReceiveCompletedEventHandler_A ReceiveCompleted;

    public void OnRaiseReceiveCompletedEvent(string myData)
    {
        ReceiveCompletedEventArgs_A rc;
        try
        {
            rc = new ReceiveCompletedEventArgs_A { myData = myData };
            // Uncomment below line, to see an exception being handled.
            //throw new Exception("Testing exception handling");
        }
        catch (Exception ex)
        {
            rc = new ReceiveCompletedEventArgs_A { innerException = ex };
        }

        if (ReceiveCompleted != null)
            ReceiveCompleted(this, rc);
    }
}

// A Subscriber of ReceiveCompleted event, with "innerException" mechanism.
public class RCSubscriber_A
{
    public void Initialize(RCPublisher_A rcp)
    {
        rcp.ReceiveCompleted += OnReceiveCompleted;
    }

    private void OnReceiveCompleted(object sender, ReceiveCompletedEventArgs_A rc)
    {
        if (rc.innerException != null)
        {
            // Handle the exception
        }
        else
        {
            // Use rc.myData
        }
    }
}
方法B:

// ========== B: "Out-of-band" handling of exceptions; not multi-cast ==========
// (Successful events are multi-cast, but exceptions are sent to a single delegate.)

public class ReceiveCompletedEventArgs_B
{
    public string myData;   // Set on successful events (no exception).
}

public delegate void ReceiveCompletedEventHandler_B(object sender, ReceiveCompletedEventArgs_B args);

public delegate void ExceptionDelegate(Exception ex);

// The Publisher of ReceiveCompleted event, with out-of-band Exception handling.
public class RCPublisher_B
{
    // Called when the event is successful (no exception).
    public event ReceiveCompletedEventHandler_B ReceiveCompleted;

    // Called when there is an exception.
    public ExceptionDelegate exceptionDeleg;

    public void OnRaiseReceiveCompletedEvent(string myData)
    {
        try
        {
            ReceiveCompletedEventArgs_B rc = new ReceiveCompletedEventArgs_B { myData = myData };
            // Uncomment below line, to see an exception being handled.
            //throw new Exception("Testing exception handling");

            if (ReceiveCompleted != null)
                ReceiveCompleted(this, rc);
        }
        catch (Exception ex)
        {
            if (exceptionDeleg != null)
                exceptionDeleg(ex);
            // What to do if there is no exceptionDeleg:
            //   If below line is commented out, unhandled exceptions are swallowed.
            //   Uncomment, to throw them to your app-level exception handler.
            else throw;
        }

    }
}

// A Subscriber of ReceiveCompleted event, with out-of-band Exception handling.
public class RCSubscriber_B
{
    public void Initialize(RCPublisher_B rcp)
    {
        rcp.ReceiveCompleted += OnReceiveCompleted;
        // CAUTION: Overrides any other exception delegate.
        // If you need multi-casting of the exception, see Approach A.
        rcp.exceptionDeleg = RCExceptionOccurred;
    }

    private void OnReceiveCompleted(object sender, ReceiveCompletedEventArgs_B rc)
    {
        // Use rc.myData
    }

    private void RCExceptionOccurred(Exception ex)
    {
        // Use ex.
    }
}
方法C:

// ========== C: Wrap "innerException" into custom Exception, for app-level handler ==========
// Similar to B, but instead of adding ExceptionDelegate and exceptionDeleg,
// Define a custom exception type, and throw it.
// Catch it inside your app-level handler.
public class ReceiveCompletedException : Exception 
{
    public Exception innerException;
}

public class RCPublisher_C
{
    public event ReceiveCompletedEventHandler_B ReceiveCompleted;

    public void OnRaiseReceiveCompletedEvent(string myData)
    {
        ReceiveCompletedEventArgs_B rc;
        try
        {
            rc = new ReceiveCompletedEventArgs_B { myData = myData };
            // Uncomment below line, to see an exception being handled.
            //throw new Exception("Testing exception handling");

            if (ReceiveCompleted != null)
                ReceiveCompleted(this, rc);
        }
        catch (Exception ex)
        {
            throw new ReceiveCompletedException{ innerException =  ex };
        }
    }
}

// ...
// In your app-level handler:
        // ...
        catch (ReceiveCompletedException rce)
        {
           // If it gets here, then an exception happened in ReceiveCompleted code.
           // Perhaps you have some graceful way of restarting just that subsystem.
           // Or perhaps you want a more accurate log, that instead of just saying
           // "Exception XYZ happened" (the inner exception), logs that it was
           // ReceiveCompleted that has the problem.
           // use rce.innerException
        }
        // ...


您正在抛出异常,而不是处理它?抱歉,但在您的代码狙击手中,您只是为您的事件订阅了一个处理程序。你的朋友不喜欢它。第二个try/catch块没有意义(除非您有一个自定义的事件添加/删除处理程序)。您试图在错误的位置捕获异常。异常不会在向事件注册处理程序的行中抛出,而是在触发(调用)该事件的行中抛出。这一行没有显示在上面的代码中。而且,所有这些
catch{throw;}
位都没有任何作用,也不做任何事情,应该删除。我猜其中有一个相应的
EndReceive
,也有
EndInvoke
。在异步调用中,您在
EndInvoke
中捕获异常,而不是在
BeginInvoke
中捕获异常。您正在抛出异常,而不是处理它?抱歉,但在代码snipper中,您只是为事件订阅了一个处理程序。你的朋友不喜欢它。第二个try/catch块没有意义(除非您有一个自定义的事件添加/删除处理程序)。您试图在错误的位置捕获异常。异常不会在向事件注册处理程序的行中抛出,而是在触发(调用)该事件的行中抛出。这一行没有显示在上面的代码中。而且,所有这些
catch{throw;}
位都没有任何作用,也不做任何事情,应该删除。我猜其中有一个相应的
EndReceive
,也有
EndInvoke
。在异步调用中,您在
EndInvoke
中捕获异常,而不是
BeginInvoke
。。。而对于那个在“捕获块”中提出解决方案的人,在被否决后删除了他们的答案:我明白了你想说什么。不要泄气。(我不是那个否决你的人。)看看@gustavo的评论;关于ReceiveCompleted,您可能还需要做更多的工作,但这是一个单独的问题。你能说说你希望发生什么吗?谢谢你们的回复。。。我试图理解的是如何抛出委托方法\u msgQ\u receivecompleted中发生的异常。例如,我收到消息,然后调用一个SQL方法(引用的dll)来写入数据。如果这引发了一个异常,我想停止这个过程,并在控制台应用程序上打印一些东西。我认为@Gustavo所说的是,我需要做更多的事情来接收CompletedEventHandler来实现这一点。我想这就是我不理解的-很抱歉,新来的代理和MQ->一直试图找到任何没有运气的示例..Ridoy-啊,很清楚-调用块(ReceiveCompletedEventHandler块)没有捕获异常它在委托类中被捕获,当它点击“throw”时,我在代码中得到未处理的异常错误..@Tim。好的,我是倒着读的。我的书面回答不会有帮助——它在错误的地方,你不能在你试图“抛出”异常的地方。您必须在catch块中捕获它,并自己调用一些方法。这意味着您需要一个“回调挂钩”。创建处理程序时传递的函数参数。将该函数引用存储在局部变量中,并在“catch”中调用它,然后将异常传递给它。不是我答案中的“陷阱”——发生异常的那个。太累了,现在想不出代码。。。还有那个