[英]Simple Parallel Tasks with Continuation
我已经阅读了两个小时,但我仍然感到困惑。 有人说使用StartNew,有人说Task。运行有人说其他。 我确实知道Task.Run给我一个编译错误。
我需要并行启动多个任务,然后在每个任务成功完成后执行一个继续任务。 知道何时完成所有阻塞操作将很有帮助。
这是我所拥有的:
public void DoSomeWork(object workItem)
{
var tasks = new Task<ResultArgs>[_itemList.Count];
for (int loopCnt = 0; loopCnt < _itemList.Count; loopCnt++)
{
tasks[loopCnt] = new Task<ResultArgs>.Run(() =>
{
return _itemList[loopCnt].Analyze(workItem);
});
tasks[loopCnt].ContinueWith(ReportResults, TaskContinuationOptions.ExecuteSynchronously);
}
}
编译显示“任务”中不存在“运行”。
显然,我正在运行某些东西,但我不知道该怎么办。
我如何克服这个问题?
您可以使用async
方法,也可以将项目流到数据流中,以下代码使用Tpl-dataflow
处理项目,将其传递到第二个处理步骤,最后等待处理完成。
using NUnit.Framework;
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
namespace AsyncProcessing {
[TestFixture]
public class PipelineTests {
[Test]
public async Task RunPipeline() {
var pipeline = new MyPipeline();
var data = Enumerable.Range(0, 1000).Select(x => new WorkItem(x, x));
foreach(var item in data) {
await pipeline.SendAsync(item);
}
pipeline.Complete();
await pipeline.Completion;
//all processing complete
}
}
class MyPipeline {
private BufferBlock<WorkItem> inputBuffer;
private TransformBlock<WorkItem, WorkItem> analyzeBlock;
private TransformBlock<WorkItem, ResultArg> reportBlock;
private ActionBlock<ResultArg> postOutput;
public ConcurrentBag<ResultArg> OutputBuffer { get; }
public Task Completion { get { return postOutput.Completion; } }
public MyPipeline() {
OutputBuffer = new ConcurrentBag<ResultArg>();
CreatePipeline();
LinkPipeline();
}
public void Complete() {
inputBuffer.Complete();
}
public async Task SendAsync(WorkItem data) {
await inputBuffer.SendAsync(data);
}
public void CreatePipeline() {
var options = new ExecutionDataflowBlockOptions() {
MaxDegreeOfParallelism = Environment.ProcessorCount,
BoundedCapacity = 10
};
inputBuffer = new BufferBlock<WorkItem>(options);
analyzeBlock = new TransformBlock<WorkItem, WorkItem>(item => {
//Anylyze item....
return item;
}, options);
reportBlock = new TransformBlock<WorkItem, ResultArg>(item => {
//report your results, email.. db... etc.
return new ResultArg(item.JobId, item.WorkValue);
}, options);
postOutput = new ActionBlock<ResultArg>(item => {
OutputBuffer.Add(item);
}, options);
}
public void LinkPipeline() {
var options = new DataflowLinkOptions() {
PropagateCompletion = true,
};
inputBuffer.LinkTo(analyzeBlock, options);
analyzeBlock.LinkTo(reportBlock, options);
reportBlock.LinkTo(postOutput, options);
}
}
public class WorkItem {
public int JobId { get; set; }
public int WorkValue { get; set; }
public WorkItem(int id, int workValue) {
this.JobId = id;
this.WorkValue = workValue;
}
}
public class ResultArg {
public int JobId { get; set; }
public int Result { get; set; }
public ResultArg(int id, int result) {
this.JobId = id;
this.Result = result;
}
}
}
为什么不使用Parallel.ForEach循环。 这用于并行执行任务,它可以使用多个线程,执行速度更快的Parallet.Foreach
但是,如果您要进行一些涉及锁定的数据库相关的输入输出操作,则可能会失败。 在那种情况下,我建议在每个任务中保留一个返回类型,并根据上一个任务的返回类型启用ext任务。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.