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