JChung2006 said:

Implement an UnhandledExceptionHandler and log the exception information to the Event Log so that you can get better information about what is causing your application to crash and in what context.

// C# 2.0
static void Main(string[] args)
{
  AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(
    delegate(object sender, UnhandledExceptionEventArgs e) {
      if (e.IsTerminating) {
        object o = e.ExceptionObject;
        Debug.WriteLine(o.ToString()); // use EventLog instead
      }
    }
  );

  // rest of your Main code
}
// C# 3.0
static void Main(string[] args)
{
  AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(
    (sender, e) => {
      if (e.IsTerminating) {
        object o = e.ExceptionObject;
        Debug.WriteLine(o.ToString()); // use EventLog instead
      }
    }
  );

  // rest of your Main code
}
' Visual Basic -- anonymous methods WRU?
Sub UnhandledExceptionEventRaised(ByVal sender As Object, ByVal e As UnhandledExceptionEventArgs)
  If e.IsTerminating Then
    Dim o As Object = e.ExceptionObject
    Debug.WriteLine(o.ToString) ' use EventLog instead
  End If
End Sub

Sub Main()
  AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf UnhandledExceptionEventRaised

  ' rest of your Main code
End Sub
Thanks for that tip JChung2006 of using the unhandled exception handler!  It helped me find my true problem, which had absolutely nothing to do with threading, but rather that I was sending a string that was TOO LARGE to the event log!