2013-11-15 130 views
0

我有以下的异步代码:执行异步代码同步

public async Task<List<PreprocessingTaskResult>> Preprocess(Action onPreprocessingTaskFinished) 
{ 
    var preprocessingTasks = BuildPreprocessingTasks(); 

    var preprocessingTaskResults = new List<PreprocessingTaskResult>(); 

    while (preprocessingTasks.Count > 0) 
    { 
    //Wait till at least one task is completed 
    await TaskEx.WhenAny(preprocessingTasks.ToArray()); 

    onPreprocessingTaskFinished(); 
    } 

    return 
} 

和异步使用代码

var preprocessingTaskResults = await Preprocess(someAction); 

在某些情况下,我需要调用它同步的方式。对于比较简单的情况下(如异步方法只返回一个任务),我以前做到以下几点:

var someTask = AsyncMethod(); 
Task.Wait(someTask); 

但我很困惑我应该如何在这里实现它。

+1

最好的解决方案实际上不会创建任务,只返回一些委托并直接调用它,这可以在BuildPreprocessingTasks – Andrey

回答

3

任务的Result属性将被阻塞,直到任务完成,然后返回它的结果:

List<PreprocessingTaskResult> result = Preprocess(someAction).Result; 

http://msdn.microsoft.com/en-us/library/dd321468(v=vs.110).aspx

+0

中完成。问题在于它经常会导致死锁。 – svick

+0

只有在使用同步上下文的环境中时才适用。如果确实会导致死锁,请阅读以下内容:http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html – dcastro

1

有没有简单的方法来同步调用异步代码。斯蒂芬图博涵盖了一些不同的方法here,但没有办法适用于所有情况。

最好的解决方案是将同步调用代码更改为异步。随着Microsoft.Bcl.Async和最近发布的Xamarin的出现,异步代码现在支持.NET 4.0(及更高版本),Windows Phone 7.1(及更高版本),Windows Store,Silverlight 4(及更高版本),iOS/MonoTouch,Android/MonoDroid ,以及适用于这些平台的任何组合的可移植类库。

所以这几天没有什么理由不是使用async

但是如果你绝对需要一个同步API,那么最好的解决办法就是使它一路同步。如果你确实需要异步API和同步API,这会导致代码重复,这是不幸的,但这是目前最好的解决方案。