如何在C#console app,.NET 4.5中实现并发调用?

时间:2013-09-05 19:16:06

标签: c# asynchronous parallel-processing

我正在轮询外部队列以获取作业请求,然后处理作业(大约需要1分钟)。目前,我正在同步这样做,效率很低,因为如果有10个工作,则需要10分钟。该机器可以同时处理多达5个作业,因此它应该能够在约2分钟内处理10个作业。

我从未做过多线程,我曾尝试阅读async,await,Task.Run,​​但是没有成功实现它。有关实现此伪代码的简单方法的任何建议吗?

while(concurrentJobs <= 5)
{
    job = pollForJob(); // synchronous

    processJob(job); // want to do this in background so that I can poll for next job
}

void processJob(job)
{
    concurrentJobs++;
    doStuff(); // takes 1 minute
    concurrentJobs--;
}

3 个答案:

答案 0 :(得分:3)

看起来你有一个生产者 - 消费者模型。在这种情况下,Parallel课程对你没有任何好处,因为任何时候都可以来一份新工作。当您事先知道需要做什么时,您只能使用Parallel课程。

但是,如果我可以随时使用新工作,我会使用以下方法。

生产者

写一个单独的长期Task或使用Thread。该线程从网络(例如来自队列或数据库)或其他任何东西接收作业,并将项目放入共享内存。

共享内存

使用BlockingCollection添加和接受工作。这充当了生产者和消费者之间的中介。

消费

与生成器完全相同 - 一个单独的Thread,用于检查共享内存中是否有任何可用项。从队列中检索项目后,您可以随意处理它。


现在,如果你有这样的分离,你可以很容易地产生几个生产者和消费者,每个生产者和消费者都在自己的线程中运行。

答案 1 :(得分:0)

你有没有试过每个并行?这很简单。

这是MSDN example

Parallel.ForEach(concurrentJobs , currentJob =>
{
    processJob(currentJob);
});

答案 2 :(得分:0)

Romulo's answer相似,但更加充实。

首先,您需要将pollForJob()功能转换为IEnumerable

private IEnumerable<Job> JobEnumerator()
{
   Job job;
   while((job = pollForJob()) != null)
   {
       yield return job;
   }
}

然后您可以将其与Parallel.ForEach

一起使用
Parallel.ForEach(JobEnumerator(), 
         new ParallelOptions() {MaxDegreeOfParallelism = 5}, 
         processJob);

这将阻止Parallel.ForEach行,但它将同时运行processJob(Job job)函数的5个实例。