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”中调用它,然后将异常传递给它。不是我答案中的“陷阱”——发生异常的那个。太累了,现在想不出代码。。。还有那个