我有以下代码,当它试图抛出错误时,它给了我一个“用户代码未处理的异常”:
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;
}
}
通过以下方法调用(以前的代码段):
public void MSMQ_GetMessage(string _MQ_Path)
{
try
{
//set the correct message queue
MessageQueue _msgQ = new MessageQueue(_MQ_Path, QueueAccessMode.ReceiveAndAdmin);
//set the format of the message queue
_msgQ.Formatter = new XmlMessageFormatter(new Type[] { typeof(_TwitterStreamFeed) });
try
{
_msgQ.ReceiveCompleted += new ReceiveCompletedEventHandler(_msgQ_RecieveCompleted);
}
catch
{
throw;
}
IAsyncResult _result = _msgQ.BeginReceive();
_asyncList.Add(_result); // asyncList is a global variable of type System.Collections - > this allows the callback to remain open and therefore nit garbage collected while the async thread runs off on it's own
}
catch (Exception _ex)
{
throw new Exception("_msgQ_get Message threw the following error :- " + _ex);
}
catch
{
throw;
}
}
你能帮助我理解为什么错误没有被回到ReceiveCompletedEventHandler
电话?我知道它正在不同的线程上执行代码,但我不明白 MSDN 示例如何捕获异常。我期待异常返回到 try / catch 阻止。
答案 0 :(得分:5)
以下是四种方法。
在方法“A”中,Exception对所有订阅者进行多播。这是通过在自定义EventArgs类中包含Exception实例作为“innerException”字段来完成的。
在方法“B”中,异常通过调用单独的委托来处理“带外”(不是多播,不是事件机制的一部分)。
在方法“C”中,您有一个应用程序级异常处理程序。 您希望通知它此异常是在处理ReceiveCompleted时发生的。 通过定义(并抛出)ReceiveCompletedException来执行此操作,该事务具有“innerException”字段以包含实际异常。
在方法“D”(下面没有给出代码)中,您不关心ReceiveCompleted代码中发生的异常。您只需要一个通用的位置来处理异常。这称为“应用程序级异常处理”。见Catch-all error handling on application level?
方法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
}
// ...