2

MSMQ に関するエラーが発生しましたが、オンラインで解決策が見つかりません。スタックトレースは次のとおりです。

System.Messaging.MessageQueueException (0x80004005): An invalid handle was passed to the function.
at System.Messaging.MessageQueue.ReceiveCurrent(TimeSpan timeout, Int32 action, CursorHandle cursor, MessagePropertyFilter filter, MessageQueueTransaction internalTransaction, MessageQueueTransactionType transactionType)
at System.Messaging.MessageQueue.Peek(TimeSpan timeout, Cursor cursor, PeekAction action)
at Utility.Msmq.MsmqManager.PeekWithoutTimeout(Cursor cursor, PeekAction action)
at Utility.Msmq.MsmqManager.SearchMessages(List`1 labels)

キューは、次のコードを使用して初期化されます。

var queuePath = isIp
    ? (machineName == "127.0.0.1"
            ? string.Format(@".\Private$\{0}", queueName)
            : string.Format("FormatName:Direct=OS:{0}\\private$\\{1}", machineName,
                            queueName))
    : string.Format("FormatName:Direct=TCP:{0}\\private$\\{1}", machineName, queueName);

try
{
    _queue = MessageQueue.Exists(queuePath)
                    ? new MessageQueue(queuePath)
                    : MessageQueue.Create(queuePath, true);
    _queue.MessageReadPropertyFilter.Priority = true;
    _queue.SetPermissions("Everyone", MessageQueueAccessRights.FullControl);
}
catch(MessageQueueException)
{
    // Concurrent threads on a new company will try to create the queue at once, which throws an error
    // If this happens, wait 100ms, then check if queue was created by some other thread, and return it.
    while (!MessageQueue.Exists(queuePath))
    {
        Thread.Sleep(100);
    }
    _queue = new MessageQueue(queuePath);
}

これは、msmq でピークを実行するコードです。

private Message PeekWithoutTimeout(Cursor cursor, PeekAction action)
{
    Message ret = null;
    try
    {
        ret = _queue.Peek(new TimeSpan(1), cursor, action);
    }
    catch (MessageQueueException mqe)
    {
        if (mqe.MessageQueueErrorCode != MessageQueueErrorCode.IOTimeout)
        {
            throw;
        }
    }
    catch (Exception generalException)
    {
        Loggers.CreateBillLogger.Error(generalException.Message, generalException);
        throw generalException;
    }

    return ret;
}

public List<Message> SearchMessages(List<string> labels)
{
    var count = 0;
    var cursor = _queue.CreateCursor();
    var messages = new List<Message>();

    var message = PeekWithoutTimeout(cursor, PeekAction.Current);
    if (message != null)
    {
        if (labels.Contains(message.Label))
        {
            messages.Add(message);
        }

        do
        {
            message = PeekWithoutTimeout(cursor, PeekAction.Next);
            if (message != null && labels.Contains(message.Label))
            {
                messages.Add(message);
            }
        } while (message != null);
    }

    return messages;
}

PS注意すべきことの1つは、このコードはBackgroundWorkersを使用してマルチスレッド環境で実行され、2つ以上のスレッドが一度にキューを作成しようとする大きな変更があり、同時作成につながることです。この問題は、catch ブランチで解決されました。

私が間違っていることはありますか?ありがとう !

4

1 に答える 1

0

この問題とほぼ完全に一致する非常に古い .NET フレームワーク バージョンに問題があるようです。同じ問題が時々発生するため、私はそれとあなたの投稿を見つけました。

KB 826297は、マルチスレッド環境で ReceiveById を呼び出すときに発生するこの問題について説明しています。

編集:ロックステートメントで修正するのに十分だと思いましたが、ヘルプ記事を読み間違えました。KB記事のハックを使用する必要があるようです

于 2013-12-11T16:24:23.487 に答える