2010-04-27 33 views
6

我有一个程序(C#)和一个测试列表。
另外,我有两个线程。一个将任务添加到列表中,另一个读取并从中删除执行的任务。
每次有一个线程想要访问列表时,我都使用'lock'函数。
我想要做的另一件事是,如果列表为空,那么需要从列表中读取的线程将会休眠。并在第一个线程将任务添加到列表中时唤醒。 这里是我写的代码:使用c锁共享数据#

... 
List<String> myList = new List(); 
Thread writeThread, readThread; 
writeThread = new Thread(write); 
writeThread.Start(); 
readThraed = new Thread(read); 
readThread.Start(); 
... 
private void write() 
{ 
    while(...) 
    { 
    ... 
    lock(myList) 
    { 
     myList.Add(...); 
    } 
    ... 
    if (!readThread.IsAlive) 
    { 
     readThraed = new Thread(read); 
     readThread.Start(); 
    } 
    ... 
    } 
    ... 
} 

private void read() 
{ 
bool noMoreTasks = false; 
    while (!noMoreTasks) 
    { 
     lock (MyList)//syncronize with the ADD func. 
     { 
       if (dataFromClientList.Count > 0) 
       { 
        String task = myList.First(); 
        myList.Remove(task); 
       } 
       else 
       { 
        noMoreTasks = true; 
       }  
     } 
     ... 
    } 
    readThread.Abort(); 
} 

显然,我这样做是错误的,并预期它不执行(该readTread开不从列表中读取)。
有谁知道我的问题是什么,以及如何使它正确?
非常感谢,

回答

3

你需要的是一个阻塞队列。它就像一个普通的队列,除了出队方法块,如果没有排队。 Here是一个实现。一旦你实现了阻塞队列,那么其他一切都很容易。只要小心你使用的阻塞队列的实现。我已经看到很多有微妙线程问题的例子。坚持我提供的链接可能是最好的。

public class Example 
{ 
    private BlockingQueue<Task> m_Queue = new BlockingQueue<Task>(); 

    public void StartExample() 
    { 
    Thread producer = new Thread(() => Producer()); 
    Thread consumer = new Thread(() => Consumer()); 
    producer.Start(); 
    consumer.Start(); 
    producer.Join(); 
    consumer.Join(); 
    } 

    private void Producer() 
    { 
    for (int i = 0; i < 10; i++) 
    { 
     m_Queue.Enqueue(new Task()); 
    } 
    } 

    private void Consumer() 
    { 
    while (true) 
    { 
     Task task = m_Queue.Dequeue(); 
    } 
    } 
} 
+0

感谢您的快速回答,我想尝试您的答案,但我没有BlockingQueue类。我需要添加一些使用? – menacheb 2010-04-27 14:33:29

+0

深呼吸并再次阅读答案;这一次慢点。 Brian在答案中提供了一个BlockingQueue类实现的链接。 – 2010-04-27 14:47:00

+0

.NET 4.0中包含BlockingQueue实现。 – 2010-04-30 13:22:57