2015-07-01 20 views
3

我有一个队列奏效的方法。在消耗队列中的第一个对象之后,它会进入睡眠状态一段预定的时间(比如10秒)。如果队列在第三或第四秒被任何其他线程修改,是否有办法唤醒该线程?从休眠模式唤醒线程了,当一个集合被修改

+1

你是什么意思的“去睡觉”?你使用Thread.Sleep方法或其他东西? – Fabjan

+0

是的。我正在使用Thread.Sleep方法。 – Ganesh

+0

是的,将您的收藏改为'System.Collections.Concurrent.BlockingCollection' –

回答

0

谢谢大家对你的建议的选项。我终于在这个需求上解决了AutoResetEvent。在消耗队列中的第一个对象之后,我不会将主线程设置为Sleep,而是从主线程中派生出一个新线程,并在那里调用sleep。主线只会等待。一旦新线程唤醒,它将使用Set信号通知主线程,主线程将恢复。这是一部分。

第二部分 - 如果任何其他线程修改队列,那么即使该线程也会在同一个EventWaitHandle上调用Set,从而再次使主线程恢复。

这可能不是最佳解决方案,但比其他方法更简单。

5

您应该使用专门为这样的目的而设计的集合。其中一个例子是BlockingCollection,它允许您从集合中获取物品,并且如果没有物品可用,该方法将会阻塞,直到有物品提供给您。它也是一个专门设计用于从多个线程操纵的集合,缓解了同步的负担。

注意BlockingCollection可以使之与不同类型的集合的支持初始化。默认情况下,它会使用一个ConcurrentQueue,但也有在System.Collections.Concurrent命名空间,如果你不想排队语义(好像你这样做虽然),您可以使用其他集合。如果你确实需要一些独特的东西,你也可以实现你自己的收集实现IProducerConsumerCollection<T>

-1

我会把线程进入一个while迭代,然后睡眠时间减少到像200毫秒。

但在每次迭代我会检查队列是否被修改。 通过这种方式,线程始终处于睡眠模式,并在队列被修改时唤醒。

当您想要停止线程时,您只需将while条件设置为false

0

Servy有这个使用Blocking Collection正确的答案。

只需进一步添加:当“工作”项在队列中可用并在该线程上异步处理它时,它会创建一个新的线程池线程。

你可以在一个生产者/消费者队列使用一个:

例如为:

/// <summary> 
/// Producer/consumer queue. Used when a task needs executing, it’s enqueued to ensure order, 
/// allowing the caller to get on with other things. The number of consumers can be defined, 
/// each running on a thread pool task thread. 
/// Adapted from: http://www.albahari.com/threading/part5.aspx#_BlockingCollectionT 
/// </summary> 
public class ProducerConsumerQueue : IDisposable 
{ 
    private BlockingCollection<Action> _taskQ = new BlockingCollection<Action>(); 

    public ProducerConsumerQueue(int workerCount) 
    { 
     // Create and start a separate Task for each consumer: 
     for (int i = 0; i < workerCount; i++) 
     { 
      Task.Factory.StartNew(Consume); 
     } 
    } 

    public void Dispose() 
    { 
     _taskQ.CompleteAdding(); 
    } 

    public void EnqueueTask(Action action) 
    { 
     _taskQ.Add(action); 
    } 

    private void Consume() 
    { 
     // This sequence that we’re enumerating will block when no elements 
     // are available and will end when CompleteAdding is called. 
     // Note: This removes AND returns items from the collection. 
     foreach (Action action in _taskQ.GetConsumingEnumerable()) 
     { 
      // Perform task. 
      action(); 
     } 
    } 
} 
相关问题