C# 链接具有不同返回类型的任务

C# 链接具有不同返回类型的任务,c#,.net,.net-4.0,task-parallel-library,C#,.net,.net 4.0,Task Parallel Library,是否可以使用不同的退货类型或根本不使用退货类型来链接任务?例如,在伪代码中: Task.ContinueWith(任务)。ContinueWith(任务)。ContinueWith(任务) 或者这里是真实的代码示例: private-double-SumRootN(int-root) { 双结果=0; 对于(int i=1;i{return SumRootN(j);}); } 任务=任务。继续((t)=> {//我不想从这个任务返回任何东西,但我必须,让它编译 this.statusText.

是否可以使用不同的退货类型或根本不使用退货类型来链接任务?例如,在伪代码中:

Task.ContinueWith(任务)。ContinueWith(任务)。ContinueWith(任务)
或者这里是真实的代码示例:

private-double-SumRootN(int-root)
{
双结果=0;
对于(int i=1;i<10000000;i++)
{
结果+=Math.Exp(Math.Log(i)/root);
}
返回结果;
}
私有无效任务顺序继续按钮(对象发送者,路由目标e)
{
Task=null;
this.statusText.Text=“”;
this.watch=Stopwatch.StartNew();
对于(int i=2;i<20;i++)
{
int j=i;
如果(任务==null)
{
task=task.Factory.StartNew(()=>{return-SumRootN(j);});
}
其他的
{
task=task.ContinueWith((t)=>{return SumRootN(j);});
}
任务=任务。继续((t)=>
{//我不想从这个任务返回任何东西,但我必须,让它编译
this.statusText.Text+=String.Format(“根{0}:{1}\n”,j,t.Result);
返回t.Result;
},TaskScheduler.FromCurrentSynchronizationContext());
}
任务。继续((t)=>
{//我也不想在这里返回任何东西,但我似乎不必在这里返回,即使intellisense需要一个任务??
this.statusText.Text+=String.Format(“{0}毫秒已用\n”,watch.elapsedmillesons);
},TaskScheduler.FromCurrentSynchronizationContext());
}

有关链接的奇怪之处,请参阅内联注释。

重复使用单个
任务
变量会使代码变得复杂。看起来您想要启动许多任务并等待它们完成。像这样的方法应该会奏效:

SynchronizationContext context = SynchronizationContext.Current;

Task[] tasks = Enumerable.Range(2, 19)
    .Select(d => Task<double>.Factory.StartNew(() => SumRootN(d))
        .ContinueWith(t => {
            this.statusText.Text += string.Format("root {0} : {1}\n", d, t.Result);
        }))
    .ToArray();

Task.Factory.StartNew(() => {
    Task.WaitForAll(tasks);
    string msg = string.Format("{0}ms elapsed\n", watch.ElapsedMilliseconds);
    context.Post(_ => { this.statusText.Text += msg; }, null);
});
SynchronizationContext=SynchronizationContext.Current;
任务[]任务=可枚举。范围(2,19)
.Select(d=>Task.Factory.StartNew(()=>SumRootN(d))
.ContinueWith(t=>{
this.statusText.Text+=string.Format(“根{0}:{1}\n”,d,t.Result);
}))
.ToArray();
Task.Factory.StartNew(()=>{
Task.WaitForAll(任务);
string msg=string.Format(“{0}毫秒经过\n”,watch.elapsedmillesons);
context.Post({this.statusText.Text+=msg;},null);
});
编辑:如果要创建任务链,这可能会起作用:

Task first = new Task(() => { });
Task outer = Enumerable.Range(2, 19)
    .Aggregate(first, (task, d) => {
        Task inner = new Task<double>(() => SumRootN(d))
            .ContinueWith(rt => {
                this.statusText.Text += String.Format("root {0} : {1}\n", d, rt.Result);
            });
        return task.ContinueWith(inner);
    });

outer.ContinueWith(t => {
    this.statusText.Text += String.Format("{0}ms elapsed\n", watch.ElapsedMilliseconds);
});

first.Start();
Task first=新任务(()=>{});
任务外部=可枚举范围(2,19)
.聚合(第一,(任务,d)=>{
任务内部=新任务(()=>SumRootN(d))
.ContinueWith(rt=>{
this.statusText.Text+=String.Format(“根{0}:{1}\n”,d,rt.Result);
});
返回任务。继续(内部);
});
外部。继续(t=>{
this.statusText.Text+=String.Format(“{0}毫秒已用\n”,watch.elapsedmillesons);
});
首先,开始();

如果要将
任务
与不同的返回类型关联起来,只需将它们分别放入不同的变量中即可:

Task<Type1> task1 = Task.Factory.StartNew(() => Compute1());
Task<Type2> task2 = task1.ContinueWith(_ => Compute2());
Task<Type3> task3 = task2.ContinueWith(_ => Compute3());
Task task1=Task.Factory.StartNew(()=>Compute1());
任务task2=task1.ContinueWith(=>Compute2());
任务task3=task2.ContinueWith(=>Compute3());
对于您的特定情况,您在循环中计算某些内容,并希望在每次迭代后报告UI线程,您可以这样做:

var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

Task.Factory.StartNew(() =>
{
    for (int i = 2; i < 20; i++)
    {
        // perform computation

        Task.Factory.StartNew(() =>
        {
            // report result
        }, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
    }
});
var-uiScheduler=TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(()=>
{
对于(int i=2;i<20;i++)
{
//进行计算
Task.Factory.StartNew(()=>
{
//报告结果
},CancellationToken.None,TaskCreationOptions.None,uiScheduler);
}
});

这将在代码执行时冻结UI。您确实不应该在
SynchronizationContext
上执行
Wait()
(或
WaitForAll()
)。该代码确实更简单,但我正在尝试将任务链接在一起,以便它们在后台按顺序执行。我的意思是SumRootN(2)->在UI中显示结果->SumRootN(3)->在UI中显示结果->…->显示总时间。我知道并行执行要快得多,但实际上我只是想举一个例子,说明如何连接顺序链(可能链中的每个“链接”都有不同的返回类型)。具体来说,因为您有一个单独的串行任务,您只想报告进度,并且在完成时,只需使用单个BackgroundWorker实例(它会自动处理在UI线程上调用ShowProgress和completed方法)而不是任务,您的代码就会简单得多。您到底有多少个
任务
s?您不能在单个
任务
中运行循环,创建
同步上下文
任务
吗?这确实是一个更好的解决方案,但如何在不同线程上的单个任务中获得UI线程上下文?我知道这可以通过Dispatcher完成,但这使得代码依赖于UI框架。是否可以传入对UI线程的引用?你能举个代码示例吗?我认为这里的代码示例可能弊大于利。你能从运行时行为的角度解释一下你在寻找什么吗?代码似乎是“扔掉”除了上次调用SUMROOTN调用之外的所有结果,因为您的连续调用不使用“T”或“Tr.Fultft”FWW,基于我想做的,您也可以考虑并行。因为它只是示例性丢弃代码。它不会在应用程序中使用。我试图创建一个顺序执行的任务链,用UI线程中运行的延续任务更新UI。更新UI的任务不需要向下一个任务传递值,但除非传递值,否则代码不会编译。因此标题为“链接不同返回类型的任务”-可能吗?谢谢,这正是我要找的。FWIW,如果你想报告我的进度