创建等待var更改的线程

时间:2013-12-02 11:37:35

标签: c# multithreading c#-4.0 thread-safety

我希望有一个单独的线程,从队列和多个线程消耗,生成工作并将其放在此队列上 - 然后允许原始生成线程能够等待(在某些时候)该工作具有已完成并继续使用该对象。

这样的事情:

loop:
1. TheThread waiting for "myObj pending" is not null.
2. Thread2 changing "pending" object.
3.1. TheThread do some stuff on "pending"
3.2. Thread2 doing some another stuff.
4. Thread2 waiting until Thread finished, and then do something on "pending" and return him to be null
[there is many "Thread"s like "Thread2", and I want it to be ThreadSafe]

我尝试在下面的代码中执行此操作,但这是我第一次使用Threads,因此我不确定我做错了什么,以及是否有效方法。

ManualResetEvent mre = new ManualResetEvent(false);
myObj pending = null;

Thread worker = new Thread(doWork);
Thread.start();
Thread Thread2 = new Thread(anotherMethod);
Thread Thread3 = new Thread(anotherMethod2); 

void doWork()
{
while (true)
    {            
        if (pending == null)
            {
                mre.waitOne()
            }
        lock(pending)
        {
            pending.doSomething();
            mre = new ManualResetEvent(false);
        }
    }
}

void anotherMethod()
{
    //doStuff
    pending = new myObj()
    mre.set();
    //doStuff
    worker.Join()
    pending.doSomeThingJustIfDoWorkDone()        
}

void anotherMethod2()
{
    //doStuff
    pending = new myObj()
    mre.set();
    //doStuff
    worker.Join()
    pending.doSomeThingJustIfDoWorkDone()        
}

4 个答案:

答案 0 :(得分:2)

使用线程时,我更喜欢使用Tasks来管理它们。

我认为任务并行库中的方法ContinueWith是您正在寻找的方法。看看这个例子,也许这可以帮到你。

http://msdn.microsoft.com/en-us/library/dd537612.aspx

答案 1 :(得分:1)

4.5中的ConcurrentExclusiveSchedulerPair完全符合您的要求。

一般情况下,您的用例在Richter的书“CLR via C#”中有所描述,称为Condition In variable pattern

internal sealed class ConditionVariablePattern {
  private readonly Object m_lock = new Object();
  private Boolean m_condition = false;
  public void Thread1() {
    Monitor.Enter(m_lock); // Acquire a mutual-exclusive lock
    // While under the lock, test the complex condition "atomically"
    while (!m_condition) {
    // If condition is not met, wait for another thread to change the condition
       Monitor.Wait(m_lock); // Temporarily release lock so other threads can get it
    }
    // The condition was met, process the data...
    Monitor.Exit(m_lock); // Permanently release lock
 }
 public void Thread2() {
    Monitor.Enter(m_lock); // Acquire a mutual-exclusive lock
   // Process data and modify the condition...
   m_condition = true;
   // Monitor.Pulse(m_lock); // Wakes one waiter AFTER lock is released
   Monitor.PulseAll(m_lock); // Wakes all waiters AFTER lock is released
   Monitor.Exit(m_lock); // Release lock
  }
}

答案 2 :(得分:0)

您可以调用worker.Join()等待工作线程完成。您可以加入多个线程。

我认为你最好不要使用Tasks而不是手动处理线程。

答案 3 :(得分:0)

你应该锁定另一个对象,因为你正在做的事情可能导致死锁  而不是挂起的对象,最好是像

这样的东西
private readonly Object  _myPendingLock = new Object();  

并且每当调用待定对象

时都应锁定此对象
 void anotherMethod()
{
 lock(_myPendingLock)
    //doStuff
    pending = new myObj()
    mew.set();
    //doStuff
    [...]
    worker.Join()
    pending.doSomeThingJustIfDoWorkDone()
 }
}

//但如果您希望生产者消费者处于最安全的状态,那么最好先看一下内置类

[ConcurrentQueue Class]