长时间停顿的并行任务

时间:2012-10-24 22:00:19

标签: c# multithreading parallel-processing task-parallel-library

我有一个符合

的功能
   private void DoSomethingToFeed(IFeed feed)
   {
      feed.SendData(); // Send data to remote server
      Thread.Sleep(1000 * 60 * 5); // Sleep 5 minutes
      feed.GetResults(); // Get data from remote server after it's processed it
   }

我想要并行化这个,因为我有很多相互独立的供稿。基于this answer,将Thread.Sleep()留在那里并不是一个好主意。我还想等待所有线程都旋转起来,直到他们都有机会获得他们的结果。

处理这样的场景的最佳方法是什么?

编辑,因为我不小心将其删除了:我最初考虑将此函数称为Parallel.ForEach(feeds, DoSomethingToFeed),但我想知道当我找到时,是否有更好的方法来处理睡眠问题我联系的答案。

4 个答案:

答案 0 :(得分:3)

我认为你应该看一下.NET中的Task类。除了更低级别的线程/线程池管理之外,它是一个很好的抽象。

为了等待所有任务完成,您可以使用Task.WaitAll

Task的使用示例如下:

IFeed feedOne = new SomeFeed();
IFeed feedTwo = new SomeFeed();

var t1 = Task.Factory.StartNew(() => { feedOne.SendData(); });

var t2 = Task.Factory.StartNew(() => { feedTwo.SendData(); });

// Waits for all provided tasks to finish execution
Task.WaitAll(t1, t2);

但是,另一种解决方案是使用Parallel.ForEach为您处理所有Task创建,并执行相应的任务批处理。对这两种方法进行了很好的比较here - 除了其他优点之外,还说明了:

  

Parallel.ForEach在内部使用分区程序将您的集合分发到工作项中。它不会对每个项目执行一项任务,而是批量处理以降低所涉及的开销。

答案 1 :(得分:3)

除非你有很多线程,否则你可以保持简单。创建所有线程。你会得到一些线程创建开销,但由于线程基本上一直在休眠,你不会得到太多的上下文切换。

编码比任何其他解决方案更容易(除非您使用的是C#5)。所以从这开始,只有在你真正看到性能问题时才能改进它。

答案 2 :(得分:1)

检查WaitHandle等待任务。

答案 3 :(得分:0)

private void DoSomethingToFeed(IFeed feed)
{
    Task.Factory.StartNew(() => feed.SendData())
        .ContinueWith(_ => Delay(1000 * 60 * 5)
                          .ContinueWith(__ => feed.GetResults())
                     );
}

//http://stevenhollidge.blogspot.com/2012/06/async-taskdelay.html
Task Delay(int milliseconds)      
{
    var tcs = new TaskCompletionSource<object>();
    new System.Threading.Timer(_ => tcs.SetResult(null)).Change(milliseconds, -1);
    return tcs.Task;
}