2013-07-10 3 views
0

Исключения У меня есть следующий код, который дает мне «Исключения был необработанным кодом пользователя», когда он пытается бросить ошибку:обработки в делегате

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 вызову? Я получаю, что он выполняет код в другом потоке, но я не понимаю из примера, как получить исключение, из примера 0DN. Я ожидал, что Исключение будет возвращено к вызову try/catch блок.

+1

вы повторно метание исключения, а не обращение с ним? – muratgu

+2

Извините, но в вашей шутке кода вы просто подписываете обработчик для своего мероприятия. Ты не любишь его. Нет значения второго блока try/catch (если у вас нет специального обработчика добавления/удаления для события). – gustavodidomenico

+0

Я обновил фрагмент с полным методом, надеюсь, будет ясным. он запутался с блоками try/catch, поскольку я только что пытался все, что мог, чтобы получить исключение из делегата .... спасибо –

ответ

4

Вот четыре подхода.

В подходе «A» Исключение используется для всех подписчиков. Это делается путем включения экземпляра Exception в качестве поля «innerException» в вашем настраиваемом классе EventArgs.

В подходе «B» исключение обрабатывается «вне диапазона» (не мульти-литой, а не частью механизма события), вызывая отдельный делегат.

В подходе «C» у вас есть обработчик исключений на уровне приложения. Вы хотите сообщить, что это исключение произошло как часть обработки ReceiveCompleted. Сделайте это, определяя (и бросая) ReceiveCompletedException, которое имеет поле «innerException», чтобы содержать фактическое исключение.

В подходе «D» (код отсутствует ниже) вам все равно, что исключение произошло в коде ReceiveCompleted. Вам просто нужно общее место для обработки исключений. Это называется «обработка исключений на уровне приложений». См Catch-all error handling on application level?

подхода:

// ========== 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 
     } 
    } 
} 

Approach 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. 
    } 
} 

Approach 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 
     } 
     // ... 
+0

.. и тому, кто предлагал решение в блоке catch, а затем удалил свой ответ после того, как он был опущен: я понял, что вы пытались сказать. Не обескураживайте. (Я не был тем, кто вас ниспровергал.) – ToolmakerSteve

+1

и см. Комментарий @ gustavo; однако может быть и больше, чем нужно делать в отношении ReceiveCompleted, что является отдельной проблемой. Можете ли вы сказать больше о том, что вы надеетесь получить? – ToolmakerSteve

+0

@ridoy - thx для редактирования – ToolmakerSteve

Смежные вопросы