【问题标题】:C# Thread Sync Monitor + ResetEventC# 线程同步监视器 + ResetEvent
【发布时间】:2012-11-04 12:49:00
【问题描述】:

我已经编写了 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...?

为什么?

【问题讨论】:

    标签: c# multithreading


    【解决方案1】:

    您的代码中的问题是,在Monitor.Wait(queueLockObj) 将退出并且线程可以处理项目之前,另一个线程(ExecuteMTAAction 方法)必须调用Monitor.Exit(queueLockObj),但调用item.waitHandle.WaitOne() 阻止了此调用-并且您有死锁.所以 - 你必须在item.waitHandle.WaitOne() 之前调用Monitor.Exit(queueLockObj)。 这段代码可以正常工作:

    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           
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-15
      • 2015-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多