InvokeRequired Exception Handling
<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>
