2

DirectSoundWrapper を作成しましたが、MTA スレッドを介してインターフェイスにアクセスできます。そこで、バックグラウンドで動作し、キューでアクションを実行するスレッドを作成しました。私はこのようなことをしました:

private void MTAQueue()
{
    lock (queueLockObj)
    {
        do
        {
            if (marshalThreadItems.Count > 0)
            {
                MarshalThreadItem item;
                item = marshalThreadItems.Dequeue();
                item.Action();
            }
            else
            {
                Monitor.Wait(queueLockObj);
            }
        } while (!disposing);
    }
}

そして、私は次のようなアクションを実行します:

private void ExecuteMTAAction(Action action)
{
    if (IsMTAThread)
        action();
    else
    {
        lock (queueLockObj)
        {
            MarshalThreadItem item = new MarshalThreadItem();
            item.Action = action;
            marshalThreadItems.Enqueue(item);

            Monitor.Pulse(queueLockObj);
        }
    }
}

しかし今、私はアクションが呼び出されるのを待ちたいと思いました。だから私は ManuelResetEvent を使いたかった:

private void ExecuteMTAAction(Action action)
{
    if (IsMTAThread)
        action();
    else
    {
        lock (queueLockObj)
        {
            MarshalThreadItem item = new MarshalThreadItem();
            item.Action = action;
            item.waitHandle = new ManualResetEvent(false); //setup
            marshalThreadItems.Enqueue(item);

            Monitor.Pulse(queueLockObj); //here the pulse does not pulse my backgrond thread anymore
            item.waitHandle.WaitOne(); //waiting
        }
    }
}

そして、私のバックグラウンドスレッドは次のように編集します:

item.Action();
item.waitHandle.Set();

問題は、バックグラウンド スレッドがもうパルス化されず、待機し続け (Monitor.Wait(queueLockObj))、アクションを呼び出すメインスレッドが manuelresetevent を待機することです...?

なんで?

4

1 に答える 1

0

あなたのコードの問題は、 before Monitor.Wait(queueLockObj)will exit と thread が item を処理できるExecuteMTAActionことMonitor.Exit(queueLockObj)ですitem.waitHandle.WaitOne()Monitor.Exit(queueLockObj)そのため、前に電話する必要がありますitem.waitHandle.WaitOne()。このコードは正常に動作します:

private void ExecuteMTAAction(Action action)
{
    if (IsMTAThread)
        action();
    else
    {
        lock (queueLockObj)
        {
            MarshalThreadItem item = new MarshalThreadItem();
            item.Action = action;
            item.waitHandle = new ManualResetEvent(false); //setup
            marshalThreadItems.Enqueue(item);

            Monitor.Pulse(queueLockObj);
        }
            item.waitHandle.WaitOne(); //waiting           
    }
}
于 2013-08-05T21:27:19.717 に答える