C# Result 和 ContinueWith 之间的区别
C# Differences between Result and ContinueWith
这两种看似做同样事情的方法有什么区别? 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( ) ) ;
}
What are the differences between this two methods that seems to do the
same thing?
区别在于前者returns 是调用者的热点任务,而后者同步阻塞,然后使用Task.FromResult
将结果重新包装在Task
中。如果您 运行 在具有自定义 SynchronizationContext
.
的环境中,后者也是 死锁 的常见情况
Can it be done even with 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;
}
task0.Result
将同步阻塞并等待 task0
完成,而 task1.ContinueWith
不会等待 task1
完成,而是 return 一个新的 Task
(当 task1
完成时将 运行)立即。
因此,您示例中的两个方法的行为并不相同。在您的第二种方法中,如果 my_ints
在传递给 WhenAll
方法时并非全部 运行 完成,则 .Result
将同步阻塞调用线程,无论时间长短my_ints
中的所有任务都需要完成,如果其中一些任务抛出异常,TaskMaxAsync2
抛出。
然而,第一个方法将 return 立即甚至 my_ints
永远不会完成或抛出异常。
Differences between Result and ContinueWith
Result
将同步阻塞直到任务完成,并将异常包装在 AggregateException
.
中
ContinueWith
将向任务注册一个回调,并在任务完成时调用该回调。
对于异步代码,Result
和 ContinueWith
都应替换为 await
。
Can it be done even with 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();
}
这两种看似做同样事情的方法有什么区别? 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( ) ) ;
}
What are the differences between this two methods that seems to do the same thing?
区别在于前者returns 是调用者的热点任务,而后者同步阻塞,然后使用Task.FromResult
将结果重新包装在Task
中。如果您 运行 在具有自定义 SynchronizationContext
.
Can it be done even with 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;
}
task0.Result
将同步阻塞并等待 task0
完成,而 task1.ContinueWith
不会等待 task1
完成,而是 return 一个新的 Task
(当 task1
完成时将 运行)立即。
因此,您示例中的两个方法的行为并不相同。在您的第二种方法中,如果 my_ints
在传递给 WhenAll
方法时并非全部 运行 完成,则 .Result
将同步阻塞调用线程,无论时间长短my_ints
中的所有任务都需要完成,如果其中一些任务抛出异常,TaskMaxAsync2
抛出。
然而,第一个方法将 return 立即甚至 my_ints
永远不会完成或抛出异常。
Differences between Result and ContinueWith
Result
将同步阻塞直到任务完成,并将异常包装在 AggregateException
.
ContinueWith
将向任务注册一个回调,并在任务完成时调用该回调。
对于异步代码,Result
和 ContinueWith
都应替换为 await
。
Can it be done even with 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();
}