2012-03-26 59 views
2

我需要建立一個進程,在WCF中監聽新的任務。 (Async) 每個任務都會被排隊(以某種方式)。C# - 隊列管理,它總是運行和出隊

什麼是最好的(邏輯和性能)方式來循環隊列和出隊。

我想過:

while(true){ 
    queue.Dequeue(); 
} 

我認爲有更好的方法來做到這一點。

謝謝

回答

7

看看System.Collections.Concurrent命名空間 - 有線程安全的隊列實現即, ConcurrentQueue - 雖然我懷疑你的需求會更好地服務於BlockingCollection

阻塞集合本質上是一個線程安全的集合,可用於生產者 - 用戶場景。在你的情況下,WCF調用將作爲生產者來添加到集合中,而工作者線程將充當消費者,他們本質上會從集合中獲取排隊的任務。通過使用單個消費者(和收集),您可以確保執行順序。如果這不重要,那麼你可以使用多個消費者線程。 (也有AddAnyTakeAny靜態重載,將允許您使用多個集合(多隊列),如果是這樣的需要。)

while(true)方法的優點是緊密的循環中避免將只消耗CPU週期。除了線程安全之外,這還可以解決排隊和排隊線程之間的同步問題。

編輯

阻塞收藏真的是非常簡單易用。請參閱下面的簡單示例 - 添加任務將從您的WCF方法調用以排隊任務,而StartConsumer將在服務啓動期間調用。

public class MyTask { ... } 

private BlockingCollection<MyTask> _tasks = new BlockingCollection<MyTask>(); 

private void AddTask(MyTask task) 
{ 
    _tasks.Add(task); 
} 

private void StartConsumer() 
{ 
    // I have used a task API but you can very well launch a new thread instead of task 
    Task.Factory.StartNew(() => 
    { 
     while (!_tasks.IsCompleted) 
     { 
      var task = _tasks.Take(); 
      ProcessTask(task); 
     } 
    }); 
} 

在停止服務,一個需要調用_tasks.CompleteAdding讓消費者線程將打破。

查找MSDN更多的例子:

http://msdn.microsoft.com/en-us/library/dd997306.aspx
http://msdn.microsoft.com/en-us/library/dd460690.aspx
http://msdn.microsoft.com/en-us/library/dd460684.aspx

+0

Thank you,Please explain ...'「while StartConsumer will be called during service啓動「我怎麼稱呼StartConsumer,我在哪裏放? – SexyMF 2012-03-26 11:31:41

+0

@SexyMF,我假設你把WCF服務打包成windows服務。實質上,你需要在啓動時啓動消費者線程,然後等待任務被添加,以便它可以處理它們! – VinayC 2012-03-26 12:25:02

+0

那麼你在說什麼_tasks應該是公共靜態的?所以生病能夠從全球asax訪問它? – SexyMF 2012-03-26 13:22:45

0

而不是無限循環,我會使用事件來同步隊列。每當進行WCF調用時,向隊列添加一個元素併發送一個「AnElementHasBeenAddedEvent」。

執行排隊任務的線程偵聽該事件,並且每當它收到它時,隊列都將被清空。

確保只有一個線程完成這項工作!

優於while(true)概念的優點:您沒有一個線程不斷循環通過無限循環,從而消耗資源。你只需要做盡可能多的工作。

+0

我同意這一點。另外:使用隊列的'Synchronized'方法作爲隊列不是線程安全的:'Queue.Synchronized(queue).Dequeue()' – MatthiasG 2012-03-26 09:08:35