2012-01-28 35 views
0

你好,我有這樣的代碼鎖定爲並行線程的單一訪問變量在C#

var queue = new BlockingCollection<int>(); 
      queue.Add(0);    
      var producers = Enumerable.Range(1, 3) 
       .Select(_ => Task.Factory.StartNew(()=> 
        { 

        Enumerable.Range(1, queue.Count) 
          .ToList().ForEach(i => 
           { 

            lock (queue) 
             { 
              if (!queue.Contains(i)) 
              { 
               Console.WriteLine("Thread" + Task.CurrentId.ToString()); 
               queue.Add(i); 
              } 
             } 
            Thread.Sleep(100); 

           }); 

        })) 
       .ToArray(); 

      Task.WaitAll(producers); 
      queue.CompleteAdding(); 

       foreach (var item in queue.GetConsumingEnumerable()) 
       {      
         Console.WriteLine(item.ToString());    
       } 

但我每次都需要一個單獨的線程的廣告東西的queue.Add(i)本 Enumerable.Range( 1,queue.Count)被激活,以便代碼執行,直到沒有更多項目被添加到隊列中。我希望你能理解這個問題。 換句話說,我需要這個動作無限地運行,直到我告訴它停止。 有什麼建議嗎?

+1

count只在'Enumerate.Range'中佔用一次,所以它不會觀察到後續在'ForEach'中的代碼所做的更改。也許如果你告訴我們你想要做什麼,我們可以提供更好的解決方案。我無法清楚地看到爲什麼要使用阻塞收集和任務並鎖定在一起。 – oleksii 2012-01-28 21:15:06

+0

很難想象你想在這裏做什麼。如果存在,代碼將始終生成一個項目的列表。也就是說,'Enumerable.Rang(1,queue.Count).ToList()'創建一個包含隊列內容的新列表。該列表從不更新。另外,如果可能有很多項目,您可能會考慮使用除隊列之外的其他項目。 'queue.contains'是一個O(N)操作,所以這將在泡泡排序的情況下執行。 – 2012-01-28 21:52:57

回答

1

我很抱歉地說,但我不能明白你寫類似的東西,沒有進一步的解釋:(

動機以任何方式對你有用下面的代碼呢?因爲我不認爲它是:P

 int n = 2; 

     Task[] producers = Enumerable.Range(1, 3).Select(_ => 
      Task.Factory.StartNew(() => 
       { 
        while (queue.Count < n) 
        { 
         lock (queue) 
         { 
          if (!queue.Contains(n)) 
          { 
           Console.WriteLine("Thread" + Task. CurrentId); 
           queue.Add(n); 

           Interlocked.Increment(ref n); 
          } 
         } 

         Thread.Sleep(100); 
        } 
       })) 
      .ToArray(); 

我的意思是,它只會繼續下去It's喜歡的只是增加數以列表的reeeeeeaaallllyyy奇怪的方式

請解釋一下你的目標,我們也許可以。幫助你。

+0

哈哈我想是的,這可以工作,我會測試它,當我回家,我很難用簡單的方式來解釋問題,我會稍後回來:P thanx – themis 2012-01-28 23:02:47

+0

嗨@Johan,我會說這個貢獻不是真的是一個有益的,建設性的和解決問題的答案。請記住,您不只是回答一個人,而是永遠將您的貢獻留在問答中。如果問題的作者不能很好地表達自己的意思,你仍然可以通過在評論中提問或編輯問題來幫助他。 – 2012-01-28 23:35:33

+0

@ achitaka-san,那是對的。這似乎是一個意見問題。我想我無法確定這種類型,如果我所製作的貢獻,但看起來他們很高興與答案無論如何。 – Johan 2012-01-29 01:05:11

1

我明白了,您需要的是隨.NET 4.0一起提供的BlockingCollection。 它允許實施生產者 - 消費者模式。

多個線程或任務可以同時向集合中添加項目。多個消費者可以同時移除項目,並且如果該收集變空,則消費線程將阻塞並等待,直到生產者添加項目。一遍又一遍... ...

...直到一個特殊的方法將被生產者稱爲識別結束,說消費者「嘿,停止等待 - 沒有什麼會再來的!」。

我不是發佈代碼示例,因爲有一些在給定的鏈接。你可以找到更多,如果你只是谷歌生產者 - 消費者模式和/或BlockingCollection

+0

thanx achitaka-san,我認爲你是對的,我需要了解生產者 - 消費者模式才能做到這一點。 – themis 2012-01-29 01:51:30