2015-07-01 16 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(); 
     } 
    } 
} 
相關問題