最近、MSMQで非同期操作に関する問題が発生しました。 .NET 2.0,3.0および3.5では、保留中の非同期受信があり、キューが削除された場合、コールバックが呼び出され、EndReceiveの呼び出し時に例外がスローされます。MSMQ非同期例外動作 - .NET 4.0と.NET 2.0
.NET 4.0では、コールバックは呼び出されませんが、例外はAppDomain.UnhandledExceptionイベントハンドラによってキャッチされます。デバッガで実行中の場合、アプリケーションはVisual Studioからの通知なしで終了し、例外が発生します。
このコードは、Windows 7 Professional、64-bitで実行されています。ただし、アプリケーションがx86またはx64をターゲットにしている場合でも、動作は同じです。 (編集:XP SP3 32ビットでこの動作が確認されています。これはOS関連ではなくフレームワークのバグです)
私は、この新しい動作が完全に新しいランタイム。この時点で何をすべきかはわかりませんが、基本的に.NET 4.0ランタイムをターゲットにしながら、.NET 4.0以前の動作を元に戻すことを目指しています。どんな助けやアドバイスも大歓迎です。ここでは、問題を再現するサンプルコードは、次のとおりです。
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);
}
}
}
補遺:ソースをSystem.Messaging(ソースステッピングを使用しようとしてあまりにも多くの時間を過ごした後
は、2.0/3.5の4.0のために利用可能ではないです、それが現れます)、2つの異なるSystem.Messagingアセンブリを使ってReflectorで狩りをすると、私はついにこの問題を発見しました。
2.0アセンブリでは、MessageQueue.AsynchronousRequest.RaiseCompletionEventメソッドでいくつかのtry/catchブロックが使用され、例外をキャッチし、.EndReceive()が呼び出されたときに例外が発生するようにエラーコードを格納します。しかし、4.0アセンブリでは、これらのtry/catchがなくなり、例外が発生した場合、プロセスはバックグラウンドスレッドで捕捉されないので終了する必要があります。
残念ながら、これは問題を解決するのに役立ちません。同期受信に切り替えることを検討していますが、このためにI/O完了ポートを利用するというアイデアが気に入っています。
あなたは確信してconnect.microsoft.comに投稿してください –
@ハンス:これまで考えていたはずです!この問題を抱えていて、同じ問題がある人は、Connectのバグがあります:http://connect.microsoft.com/VisualStudio/feedback/details/626177/messagequeue-beginreceive-asynchronous-exception-behavior –
今私はMicrosoftの接続サイトに移動するときに「ページが見つかりません」というメッセージが表示されます。誰でもこのバグの状態に関する情報を持っていますか? – DeCaf