1

在我的應用程序中,我有一組預定義的動作。我想指定特定數量的線程來執行這些操作。由於某些操作可能比其他操作花費更長時間,並且可能正在等待響應,所以當線程完成時,我希望它返回隊列並開始下一個操作。所以,作爲十個線程之一釋放,它會得到一個新的動作,等等,直到隊列爲空,然後繼續。在繼續之前,我需要等待所有的動作完成。C#.Net 2.0 .NET 4.5 TPL生產者消費者邏輯的線程池等效

所以我做了一些使用TPL的研究和測試,它在記憶之前工作得很好,「哦,廢話,我僅限於.Net 2.0在這個應用程序中」。我試圖重新使用.Net 2.0,但沒有運氣。我幾乎沒有線程處理的經驗。

誰能幫我把這個邏輯轉換成.Net 2.0嗎?

List<int> results = new List<int>(); 
var stopwatch = Stopwatch.StartNew(); 

Random random = new Random(); 
using (BlockingCollection<Action> queue = new BlockingCollection<Action>()) 
{ 
    for (int i = 0; i < 20; i++) 
    { 
     int index = i; 
     queue.Add(delegate 
         { 

          int foo = random.Next(1, 1500); 
          Thread.Sleep(foo); 
          results.Add(foo); 
          Debug.WriteLine(index + " Working: " + foo + " " + Task.CurrentId); 
         }); 
    } 
    queue.CompleteAdding(); 

    const int numWorkers = 10; 
    Task[] tasks = new Task[numWorkers]; 
    for (int i = 0; i < numWorkers; i++) 
    { 
     tasks[i] = Task.Factory.StartNew(() => 
              { 
               foreach (Action action in queue.GetConsumingEnumerable()) 
               { 
                action(); 
               } 
              }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); 
    } 
    Task.WaitAll(tasks); 
} 
Debug.WriteLine("WaitAll took {0} seconds", stopwatch.Elapsed.TotalSeconds); 
+3

「我在此應用程序中僅限於.Net 2.0」我很抱歉聽到這個消息。 – vcsjones

+0

大聲笑,感謝您的吊... ...... – SteveHansen

+0

只要2.0應用程序是一個包裝,只需調用一個4.5應用程序編寫爲Web服務。 – Servy

回答

2

我要說明我是如何做到這一段時間以前:

  1. 創建N個線程
  2. 把工作項目爲已知大小的列表
  3. 有一個共享變量int lastIndex = -1;
  4. 擁有所有的線程做到這一點:

    while(true) { 
        var index = Interlocked.Increment(ref lastIndex); 
        if (index >= list.Count) return; 
        ProcessItem(list[index]); 
    } 
    

很簡單。

把這一切都抽象成輔助方法。它應該有一個代表,以便您不需要硬編碼ProcessItem

即使對於需要確保線程池不提供並行度的確切程度的情況下,.NET 4.5也是如此。

+1

謝謝@usr我會試試這個 – SteveHansen