2015-09-12 48 views
-2

考慮下列情形單生產者多消費者的實現

private BlockingCollection<Consumer> consumers { get; set; } 


ThreadPool.QueueUserWorkItem((x) => { 

       while (consumers.Count == 0) 
        Thread.Sleep(20); 

       Consumer consumer; 
       if (consumers.TryTake(out consumer)) { 
        var result = consumer.Read(data); 
        //do stuff with result 
        if (consumers.TryAdd(consumer)) { 
         //ok 
        } 
       } 
      }); 

是否有辦法避免這種超時的時候沒有提供一個消費者來處理請求?

+0

如果你使用'主題睡覺,你做錯了什麼。爲什麼不使用'WaitHandle'來代替線程呢? – Dai

+1

你有沒有試過'System.Collections.Concurrent.BlockingCollection'爲前。它有一個有限的能力。 – Eser

+0

'消費者'的類型是什麼?你需要考慮使用[semaphore](https://msdn.microsoft.com/en-us/library/system.threading.semaphore%28v=vs.110%29.aspx)來允許消費者獲取X項目max,然後在沒有更多項目時等待事件 –

回答

2

爲您的消費者收藏使用BlockingCollection。當沒有物品可用時,它將阻止Take()呼叫,並在物品可用時立即繼續。

編輯(在OP顯示它已經使用BlockingCollection後): 將TryTake調用替換爲Take的調用,它將阻止,直到項目可用。並一起刪除Thread.Sleep調用。

編輯:添加代碼片段。

Consumer consumer = consumers.Take(); 
var result = consumer.Read(data); //do stuff with result 
if (consumers.TryAdd(consumer)) 
{ 
    //ok 
} 
+1

當OP已經使用它時,說「使用這個」的含義是什麼 – Eser

+0

@Eser我沒有注意到消費者收集聲明。也許在以後的編輯中添加? –

+0

但在你的答案之前... – Eser

5

這可能是一個遲到的答案,但我會做這樣(假設你監製產生一些字符串數據和消費者使用它們)

public class PC 
{ 
    const int THREADS = 5; 
    static BlockingCollection<string> _Collection = new BlockingCollection<string>(); 

    public PC() 
    { 
     //1 producer 
     Task.Run(()=>Producer()); 
     //N consumer 
     for (int i = 0; i < THREADS; i++) Task.Run(() => Consumer()); 
    } 

    void Producer() 
    { 
     Random rnd = new Random(); 
     while(true) 
     { 
      Thread.Sleep(100); //Not to flood our case... 
      //Produce it 
      _Collection.Add(rnd.Next().ToString()); 
     } 
    } 

    void Consumer() 
    { 
     while(true) 
     { 
      string str = _Collection.Take(); 
      //Consume it 
      Console.WriteLine("Thread \"{0}\" consumed {1}", Thread.CurrentThread.ManagedThreadId, str); 
     } 
    } 
} 
+0

這是正確的生產者 - 消費者模式。 –

+0

很好的答案,通過使用消費者中的while(true)循環,線程是否仍在運行?這會導致任何問題嗎?我應該管理他們的狀態嗎? – Hristo

+0

@Chris循環不會很緊,因爲Take()會在沒有元素可用時阻塞。 –