I recently ran into the issue of asynchronous operations in MSMQ. In .NET 2.0, 3.0, and 3.5, if there is a pending asynchronous reception, and the queue is deleted, the callback is called and an exception is thrown when calling EndReceive.
In .NET 4.0, a callback is never called, but an exception can be caught by the AppDomain.UnhandledException event handler. When launched in the debugger, the application simply stops working without notification from Visual Studio that an exception has occurred.
This code runs on Windows 7 Professional, 64-bit. However, the behavior is the same if the application is focused on x86 or x64. (Edit: this behavior is checked and on XP SP3 32-bit - this is apparently a structure error, not an OS-related one)
I assume this new behavior is because .NET 4.0 is a completely new runtime. I'm not sure what to do at the moment, but essentially I'm looking to bring back the behavior of pre-.NET 4.0, but still aiming at the .NET 4.0 runtime. Any help or advice would be greatly appreciated. Here is sample code to reproduce the problem:
class Program
{
static void Main( string[] args )
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler( CurrentDomain_UnhandledException );
string path = @".\private$\mytestqueue";
var queue = MessageQueue.Exists( path ) ? new MessageQueue( path ) : MessageQueue.Create( path );
queue.BeginReceive( TimeSpan.FromSeconds( 15 ), queue, new AsyncCallback( ReceiveComplete ) );
Thread.Sleep( 5000 );
MessageQueue.Delete( path );
}
static void CurrentDomain_UnhandledException( object sender, UnhandledExceptionEventArgs e )
{
var mqEx = (MessageQueueException) e.ExceptionObject;
Console.WriteLine( mqEx.Message );
Console.WriteLine( mqEx.MessageQueueErrorCode );
}
static void ReceiveComplete( IAsyncResult ar )
{
Console.WriteLine( "Finishing Receive." );
var queue = (MessageQueue) ar.AsyncState;
try
{
queue.EndReceive( ar );
}
catch ( MessageQueueException mqEx )
{
Console.WriteLine( mqEx.Message );
Console.WriteLine( mqEx.MessageQueueErrorCode );
}
}
}
Application:
After spending too much time trying to use source stepping (the System.Messaging source is available for 4.0, but not 2.0 / 3.5, it appears), and hunting through two different System.Messaging assemblies with Reflector, I finally found a problem.
2.0 try/catch MessageQueue.AsynchronousRequest.RaiseCompletionEvent, , .EndReceive(). 4.0 / , , , , .
, . Receive, / .