【问题标题】:C# .Net 2.0 Threadpool equivalent of .Net 4.5 TPL producer consumer logicC# .Net 2.0 线程池等效于 .Net 4.5 TPL 生产者消费者逻辑
【发布时间】:2012-12-26 13:59:48
【问题描述】:

在我的应用程序中,我有一组要执行的操作。我想指定特定数量的线程来执行操作。由于某些操作可能比其他操作花费更长的时间并且可能正在等待响应,因此当线程完成时,我希望它返回队列并开始下一个操作。因此,当十个线程之一释放时,它会执行一个新操作,依此类推,直到队列为空,然后继续。在继续之前,我需要等待所有操作完成。

所以我使用 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);

【问题讨论】:

  • “我在这个应用程序中仅限于 .Net 2.0”很遗憾听到这个消息。
  • 大声笑,谢谢你的慰问...
  • 只需将 2.0 应用程序作为一个包装器,它只调用作为 Web 服务编写的 4.5 应用程序。

标签: c# multithreading task-parallel-library threadpool consumer


【解决方案1】:

我将概述一下我之前是如何做到这一点的:

  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 中,当您需要保证线程池不提供的精确并行度时,此帮助器实际上也很有用。

【讨论】:

  • 谢谢@usr 我试试看
猜你喜欢
  • 2018-09-24
  • 2011-07-27
  • 2012-01-28
  • 1970-01-01
  • 2011-04-01
  • 2018-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多