Marshalling .NET Exceptions between Threads

Introduction

Today I faced a strange issue; I was catching an Exception in a BackgroundWorker’s thread, threw a new exception and handled it in the main GUI thread by showing the exception’s Message in a message box.

The strange thing was, that no matter what I did, the main GUI thread always displayed the message of the first generated exception in the background thread.

Cause

As described by user „nobugz“ in this discussion, the cause is:

This is an architectural limitation to the way exceptions are marshalled from one thread (the BGW’s) to another (the UI thread).  Only a single exception object can get copied, the designers chose the first one thrown as the most likely to be relevant.  You’ll need to work around this restriction.

Interestingly enough this behavior seems to occur only in an Application.ThreadException handler which seems to pick up the exception from somewhere (maybe TLS?)

Resolution

The resolution is to handle the exception directly in the RunWorkerCompleted handler where it gets forwarded to and not to throw the exception any further, until the Application.ThreadException handler of the GUI thread handles it.

Example application

To show the error in a small example project I created a tiny Windows Forms application which you may download from here.

Main Window with erroneous Behavior

When the check box is activated, the erroneous behavior is being performed when clicking the button:

The first generated exception is being displayed to the end user instead the actual one that is being thrown later in the background thread.

Main Window with expected Behavior

When the check box is not activated when clicking the button, the expected result is being displayed; the latest thrown exception:

Summary

I’ve just shown you a case where (in my eyes) the .NET Framework behaves wrong.

Maybe you find this article useful or even prove that I am wrong or how to handle in a more elegant way.

Looking forward for your feedback!

2 Gedanken zu „Marshalling .NET Exceptions between Threads

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.