是否可以链接具有不同返回类型或根本没有返回类型的任务?例如,在伪代码中:
Task<double>.ContinueWith(Task<string>).ContinueWith(Task<String>).ContinueWith(Task)
或者这里也是真实的代码示例:
private double SumRootN(int root)
{
double result = 0;
for (int i = 1; i < 10000000; i++)
{
result += Math.Exp(Math.Log(i) / root);
}
return result;
}
private void taskSequentialContinuationButton_Click(object sender, RoutedEventArgs e)
{
Task<double> task = null;
this.statusText.Text = "";
this.watch = Stopwatch.StartNew();
for (int i = 2; i < 20; i++)
{
int j = i;
if (task == null)
{
task = Task<double>.Factory.StartNew(() => { return SumRootN(j); });
}
else
{
task = task.ContinueWith((t) => { return SumRootN(j); });
}
task = task.ContinueWith((t) =>
{ // I don't want to return anything from this task but I have to, to get it to compile
this.statusText.Text += String.Format("root {0} : {1}\n", j, t.Result);
return t.Result;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
task.ContinueWith((t) =>
{ // I also don't want to return anything here but I don't seem to have to here even though intellisense expects a Task<double>??
this.statusText.Text += String.Format("{0}ms elapsed\n", watch.ElapsedMilliseconds);
}, TaskScheduler.FromCurrentSynchronizationContext());
}
请参阅内联注释以了解链接的奇怪之处。
答案 0 :(得分:3)
如果你想用不同的返回类型链接Task
,你可以把它们放在一个不同的变量中:
Task<Type1> task1 = Task.Factory.StartNew(() => Compute1());
Task<Type2> task2 = task1.ContinueWith(_ => Compute2());
Task<Type3> 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);
}
});
答案 1 :(得分:0)
您重复使用单个task
变量会使代码变得复杂。看起来您想要启动一些任务并等待它们完成。这样的事情应该有效:
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);
});
编辑:如果你想创建一系列任务,这可能有效:
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();