MSMQ-.NET 4.0 vs .NET 2.0 Asynchronous Exception Behavior

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";
        // Create queue only if it doesn't already exist.
        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;

        // .NET 4.0:

        // "The queue does not exist or you do not have sufficient
        // permissions to perform the operation."
        Console.WriteLine( mqEx.Message );
        // "QueueNotFound"
        Console.WriteLine( mqEx.MessageQueueErrorCode );
    }

    static void ReceiveComplete( IAsyncResult ar )
    {
        // This callback is never invoked under .NET 4.0.
        Console.WriteLine( "Finishing Receive." );
        var queue = (MessageQueue) ar.AsyncState;
        try
        {
            queue.EndReceive( ar );
        }
        catch ( MessageQueueException mqEx )
        {
            // .NET 2.0 through 3.5:

            // "Queue handle can no longer be used to receive messages
            // because the queue was deleted. The handle should be closed."
            Console.WriteLine( mqEx.Message );
            // "QueueDeleted"
            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, / .

+3
1

, , , . ( ), .

, Microsoft Connect, , CLR 2.0.

Microsoft Connect: http://connect.microsoft.com/VisualStudio/feedback/details/626177/messagequeue-beginreceive-asynchronous-exception-behavior

, , . , , , . , , (, BeginReceive), .

, MSMQ, .

+2

Source: https://habr.com/ru/post/1777519/


All Articles