结果与ContinueWith之间的C#差异

时间:2015-08-24 08:57:03

标签: c# asynchronous async-await task-parallel-library

这两种似乎做同样事情的方法有什么区别?即使使用async / await也能完成吗?

public Task<int> TaskMaxAsync1 ( Task<int>[] my_ints )
{
    return Task.WhenAll( my_ints )
    .ContinueWith ( x => x.Result.Where ( i => i%2 != 0 ).Max( ) ) ;
}

public Task<int> TaskMaxAsync2 ( Task<int>[] my_ints )
{
    var numbers = Task.WhenAll( my_ints ).Result ;
    return Task.FromResult( numbers.Where( i => i%2 != 0 ).Max( ) ) ;
}

3 个答案:

答案 0 :(得分:7)

  

这两种方法之间有什么区别呢?   同样的事情?

不同之处在于前者将热门任务返回给调用者,而后者同步阻塞,然后使用Task将结果重新包装在Task.FromResult中。如果您在具有自定义SynchronizationContext的环境中运行,后者也是死锁的常见情况。

  

即使使用async / await也能完成吗?

是的,它可以:

public async Task<int> MaxAsync(Task<int>[] myInts)
{
    int[] results = await Task.WhenAll(myInts);
    return results.Max(i => i % 2 != 0 ? i : (int?)null) ?? 0;
}

答案 1 :(得分:6)

  

Result和ContinueWith之间的差异

Result将同步阻止,直到任务完成,并将异常包装在AggregateException中。

ContinueWith将在任务中注册回调,并在任务完成时调用该回调。

对于异步代码,ResultContinueWith都应替换为await

  

即使使用async / await也能完成吗?

当然,像这样:

public async Task<int> MaxAsync(Task<int>[] my_ints)
{
  int[] ints = await Task.WhenAll(my_ints);
  return ints.Where(i => i % 2 != 0).Max();
}

答案 2 :(得分:3)

task0.Result将同步阻止并等待task0完成,而task1.ContinueWith将不会等待task1完成,但会返回新的Task(将在task1完成时立即运行。

因此,示例中的两个方法的行为不一样。在第二种方法中,如果my_ints在传递给WhenAll方法时并非全部完成,那么.Result将同步阻止调用线程,无论长时间内所有任务my_ints需要完成,如果其中一些抛出异常,TaskMaxAsync2会抛出。

但是第一种方法会立即返回,即使my_ints永远不会完成或抛出异常。