【问题标题】:Execute asynchronous code as synchronous以同步方式执行异步代码
【发布时间】:2023-07-26 21:06:01
【问题描述】:

我有以下异步代码:

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);

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

【问题讨论】:

  • 最好的解决方案实际上是根本不创建任务,只返回一些委托并直接调用它,这可以在 BuildPreprocessingTasks 中完成

标签: c# .net multithreading task-parallel-library


【解决方案1】:

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

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

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

【讨论】:

【解决方案2】:

同步调用异步代码没有简单的方法。 Stephen Toub 介绍了一些不同的方法here,但没有一种方法适用于所有情况。

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

所以现在几乎没有理由使用async

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

【讨论】: