我编写了一个DirectSoundWrapper,但我可以通过MTA Threads访问这些接口。 所以我创建了一个在后台工作并在队列中执行操作的Thread。 我做过这样的事情:
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))和调用动作的mainthread等待manuelresetevent ......?
为什么?
答案 0 :(得分:0)
您的代码中的问题是,在Monitor.Wait(queueLockObj)
退出并且线程可以处理项之前,另一个线程(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
}
}