Async / await in .Net - >调用没有异步实现的服务方法

时间:2015-07-16 18:01:29

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

基本上我需要使用供应商的.Net SDK提供远程请求以获取一些信息。他们的SDK在他们的方法上没有异步实现,所以我试图自己想出一些东西。我基本上想要将此请求发送到同步方法,并等待它只有一定的时间。如果请求耗时太长,我需要采取行动并在我们的网络应用程序中向客户报告。

我想知道这是否是最好的方法,还是有更好的方法?下面的代码是一个从Controller操作调用的服务方法。

{{1}}

4 个答案:

答案 0 :(得分:0)

Task.Wait有一个重载,需要int来定义超时。

public Task<bool> SignersAdded(string packageId)
{
    var timeout = 5000;

    var task = Task.Run(() =>
    {
        var package = _eslClient.GetPackage(new PackageId(packageId));
        return package != null && package.Documents.Values.Any(x => x.Signatures.Any());
    });

    if(!task.Wait(1000 /*timeout*/))
    {
        // timeout
        return false;
    }
    return task.Result;
}

答案 1 :(得分:0)

您的方法对任何内容都不while,因此它会同步运行。此外,您的Delay循环将旋转CPU,阻止调用代码,直到任务完成。

更好的方法可能就是:

TimeSpan

这样我们就可以创建一个单独的延迟任务,我们等待第一个任务完成。这将以一种真正的异步方式运行 - 没有try { DateTime.Now.ToString(tmpFormatSpec); } catch (Exception) { // the format spec is known to be bad } 循环会烧掉CPU周期。

(上面假设超时是以毫秒为单位。如果没有,则使用重载DateTime.Now.ToString("bla"); // no exception raised 取代{{1}}参数。)

答案 2 :(得分:0)

你是对的:启动一个调用GetPackage的任务。之后你可以继续做其他事情。

过了一段时间,当您需要结果时,您可以等待任务完成。但是你不必做Task.Wait。使用async / await要容易得多。

要做到这一点,你必须做三件事:

  • 声明您的功能 async
  • 而不是void返回Task而不是类型TResult返回任务<TResult&gt;。你已经做到了。
  • 而不是等待任务完成使用等待

你的功能看起来会简单得多:

public **async** Task<bool> SignersAdded(string packageId)
{
   var timeout = TimeSpan.FromSeconds(5);
   var task = Task.Run(() =>
   {
      var package = _eslClient.GetPackage(new PackageId(packageId));
      return package != null
          && package.Documents.Values
                    .Any(x => x.Signatures.Any());
    });

    // if desired you can do other things here
    // once you need the answer start waiting for it and return the result:
    return await Task;
}
  

如果你有一个返回TResult的函数,它的异步版本会返回Task <TResult&gt ;.

     

等待任务<TResult&gt;的返回值是TResult

但是,如果您希望能够等待超时,则可以执行以下操作:

var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(1);
// cancel after 1 second
try
{
    return await task.Run( () => ..., tokenSource.Token);
}
catch (OperationCanceledException exc)
{
    // handle timeout
}
finally
{
    // do necessary cleanup
}

使您的函数异步的缺点是所有调用者也必须是异步的,并且所有调用者都必须返回Task或Task <TResult&gt;。有一个例外:

  

事件处理程序可以是异步但可能返回void

示例:

private async void OnButton1_clicked(object sender,   )

答案 3 :(得分:0)

查看TaskCompletionSource和CancellationToken类。此处的示例为:Timeout an async method implemented with TaskCompletionSourceHow to cancel a TaskCompletionSource using a timout