将同步API包装到Async方法中

时间:2014-02-01 08:24:02

标签: c# asp.net-mvc asynchronous async-await

我的MVC应用程序使用库,此库的某些方法在内部调用WCF服务。从此DLL公开的所有方法都是同步的(它们都没有返回任务或任务),因为我们不拥有该程序集,所以无法将它们转换为异步API。

但是,因为这些方法调用WCF服务,所以它们是网络绑定的(因此理想情况下它们应该是异步的)。

我想在我的MVC应用程序中使用异步控制器操作,以使其更具可伸缩性。我的问题是当一个方法本质上是同步时,如何使整个方法管道等待。

异步操作 - >等待异步方法 - >等待异步方法2 - >来自库的同步方法?

我应该使用TaskCompletionSource还是Task.FromResult来包装库方法调用?

另外,如果我使用上述方法,我的代码会比同步版本更具可扩展性吗?

2 个答案:

答案 0 :(得分:5)

  

我的问题是当一个方法本质上是同步时,如何使整个方法管道等待。

你做不到。唯一的解决方案是重写dll。

  

我应该使用TaskCompletionSource还是Task.FromResult来包装库方法调用?

都不是。

  

另外,如果我使用上述方法,我的代码会比同步版本更具可扩展性吗?

没有。它会略微 可扩展。

答案 1 :(得分:0)

TaskCompletionSource<T>是一种创建木偶任务的方法,它可以在您喜欢的任何时刻完成,并且可以在您喜欢的任何时候使其成为错误。这意味着,这在您的情况下是理想的,因为您无法控制您尝试使用的API方法。以下示例将为您提供一个良好的开端。

public class HomeController : Controller
 {
    public async Task<ActionResult> Index()
    {
    ViewBag.Message = await ProcessRequest();

    return View();
    }


    //TResult -> can be of any built-in or custom type that you should decide.
    Task<TResult> ProcessRequest()
    {

    // Make a TaskCompletionSource so we can return a puppet Task
    TaskCompletionSource<TResult> tcs = new TaskCompletionSource<TResult>();

    // Call your sync API method
    SyncAPI syncApi = new SyncAPI();

    // Call api method and set the result or exception based on the output from the API //method.
    tcs.SetResult(TResult);

    // Return the puppet Task, which isn't completed yet
    return tcs.Task;
    }
}