title: InvokeRequired Exception Handling
body: <p>I noticed a few strange behaviors in a Windows Forms scenario which involves threads and UI, so, naturally, this means making use of the InvokeRequired property. The situation: my application makes use of a thread to do some work and the thread sends an event into the UI. The UI displays a message based on an Internationalization system which consists of a dictionary with keys. The I18N system cannot find a key in the dictionary and crashes.</p>
  
  <p>Notes: application is in Debug Mode and I have a try-catch over the entire "Application.Run();" back in Program.cs. However, that try-catch is not reached, as what I will discuss here is based on inner Exception handling, but I mentioned it just in case.</p>
  
  <p>So now here comes the fun parts:</p>
  
  <ol>
  <li><p>Why, for the life of me, does Visual Studio "censor" exception information from me? In the code below, you will see on the <em>if (InvokeRequired)</em> branch, a try-catch. I log the exception. ex.InnerException is NULL and the provided ex.StackTrace is anemic (only 1 step in it). Now if I <strong>comment</strong> the try-catch and simply let it crash via the Debugger, I get a much ampler stack trace. Why is that? </p></li>
  <li><p>To make things worse, <strong>neither</strong> of the two stack traces versions contain any information about the i18N crash. They just say "The given key was not present in the dictionary." and give me a stack trace up to the Invoke declaration.</p></li>
  <li><p>On the <em>else</em> branch (that is, <em>InvokeRequired == false</em>), if I put a try-catch, I can successfully catch my Exception back to the i18n system. As you can see, I tried to send my exception with InnerException back to the <em>InvokeRequired == true</em> branch. However, even so, InnerException stays NULL there and I cannot access my i18N error.</p></li>
  </ol>
  
  <p>I am puzzled by all these things and maybe somebody can help shed some light over here. If you got really strong lanterns that is.</p>
  
  <p>Here is the function's code.</p>
  
  <pre><code>private delegate void AddMessageToConsole_DELEGATE (frmMainPresenter.PresenterMessages message);
  private void AddMessageToConsole (frmMainPresenter.PresenterMessages message)
  {
    if (InvokeRequired)
    { //Catching any errors that occur inside the invoked function.
      try { Invoke(new AddMessageToConsole_DELEGATE(AddMessageToConsole), message); }
      catch (Exception ex) { MSASession.ErrorLogger.Log(ex); }
      //Invoke(new AddMessageToConsole_DELEGATE(AddMessageToConsole), message);
    }
    else
    {
      string message_text = ""; //Message that will be displayed in the Console / written in the Log.
      try
      {
        message_text = I18N.GetTranslatedText(message)
      }
      catch (Exception ex)
      {
        throw new Exception(ex.Message, ex);
      }
  
      txtConsole.AppendText(message_text);
    }
  }
  </code></pre>