Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 带延续的简单并行任务_C#_C# 4.0_Task Parallel Library - Fatal编程技术网

C# 带延续的简单并行任务

C# 带延续的简单并行任务,c#,c#-4.0,task-parallel-library,C#,C# 4.0,Task Parallel Library,我已经读了两个小时了,我仍然很困惑。有人说使用StartNew,有人说Task,有人说运行,有人说其他。我知道Task.Run给了我一个编译错误 我需要并行启动多个任务,然后在每个任务成功完成后,执行一个继续任务。知道什么时候所有的阻塞都完成了会很有帮助 以下是我所拥有的: public void DoSomeWork(object workItem) { var tasks = new Task<ResultArgs>[_itemList.Count

我已经读了两个小时了,我仍然很困惑。有人说使用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);
        }
    }
public void DoSomeWork(对象工作项)
{
var tasks=新任务[_itemList.Count];
对于(int-loopCnt=0;loopCnt<\u itemList.Count;loopCnt++)
{
tasks[loopCnt]=新任务。运行(()=>
{
返回_itemList[loopCnt].Analyze(workItem);
});
任务[loopCnt].ContinueWith(ReportResults,TaskContinuationOptions.ExecuteSynchronously);
}
}
编译程序表示任务中不存在运行

很明显,我有些事情要做,但我不知道要做什么


如何克服此问题?

为什么不使用Parallel.ForEach循环。这用于并行执行任务,它可以使用多个线程,执行速度更快


但是,如果您正在执行一些涉及锁定的与数据库相关的输入输出操作,则可能会失败。在这种情况下,我建议在每个任务中保留一个返回类型,并基于上一个任务的返回类型启用下一个任务。

您可以使用
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;
        }
    }
}
使用NUnit.Framework;
使用制度;
使用System.Collections.Concurrent;
使用System.Linq;
使用System.Threading.Tasks;
使用System.Threading.Tasks.Dataflow;
命名空间异步处理{
[测试夹具]
公共类管道测试{
[测试]
公共异步任务RunPipeline(){
var pipeline=new MyPipeline();
var data=Enumerable.Range(0,1000)。选择(x=>newworkItem(x,x));
foreach(数据中的var项){
等待管道发送异步(项目);
}
管道。完成();
等待管道完工;
//所有处理完成
}
}
类MyPipeline{
专用缓冲块输入缓冲区;
私人密码锁;
私有转换块报告块;
私有操作块输出;
公共ConcurrentBag输出缓冲区{get;}
公共任务完成{get{return postOutput.Completion;}}
公共管道(){
OutputBuffer=新的ConcurrentBag();
CreatePipeline();
链接管道();
}
公开作废完成(){
inputBuffer.Complete();
}
公共异步任务SendAsync(工作项数据){
等待inputBuffer.SendAsync(数据);
}
公共管道(){
var options=new ExecutionDataflowBlockOptions(){
MaxDegreeOfParallelism=Environment.ProcessorCount,
边界容量=10
};
inputBuffer=新的缓冲块(选项);
analyzeBlock=新转换块(项=>{
//任意项目。。。。
退货项目;
},选项);
reportBlock=新的TransformBlock(项=>{
//报告您的结果,发送电子邮件..db…等。
返回新的ResultArg(item.JobId、item.WorkValue);
},选项);
postOutput=新操作块(项=>{
OutputBuffer.Add(项);
},选项);
}
公共管道(){
var options=new DataflowLinkOptions(){
完成=真,
};
inputBuffer.LinkTo(解析块,选项);
analyzeBlock.LinkTo(报告块,选项);
链接到(postOutput,选项);
}
}
公共类工作项目{
public int JobId{get;set;}
公共int工作值{get;set;}
公共工作项(int id,int workValue){
this.JobId=id;
this.WorkValue=WorkValue;
}
}
公共类结果目标{
public int JobId{get;set;}
公共int结果{get;set;}
public ResultArg(int-id,int-result){
this.JobId=id;
结果=结果;
}
}
}

我最终使用了你提出的异步方法。我想我是对的,因为编译器没有大惊小怪。我们将在我开始测试时发现!我还将研究我以前从未见过的TPL数据流。参见数据流速成课程的编辑:)也谢谢!更多的阅读!斯蒂芬的作品通常都很好,值得一读。谢谢你的链接!我曾考虑过Parallel.ForEach,但被警告它不会将我的所有任务都放在准备运行队列中。它会限制每次的数量,因为接近实时的限制,我担心吞吐量。然而,这确实提醒了我,我需要担心异常@AeroClassics
async
如果使用defalt任务调度器,也有类似的限制。这不是我真正想听到的,而是我需要知道的。谢谢<代码>任务.运行仅存在于4.5中,不存在于4.0中。