在IAsyncResult中使用Async方法

时间:2016-09-30 12:59:18

标签: c# asynchronous async-await task-parallel-library

我正在Microsoft.ServiceBus命名空间中实现TokenProvider类。 我重写了以下方法

protected override IAsyncResult OnBeginGetToken(string appliesTo, string action, TimeSpan timeout, AsyncCallback callback,
            object state)
{
    var token = GetCustomTokenAsync(appliesTo); //How to await?
     return new CompletedAsyncResult<SharedAccessSignatureToken>(token, callback, state);
}

但正如上面的评论所述。 GetCustomTokenAsync是一种异步方法,如何在不打扰TokenProvider类签名的情况下等待?我想利用GetCustomTokenAsync的异步性质,因此我不愿意使用.Result。有没有更好的方法来解决这个问题?

2 个答案:

答案 0 :(得分:2)

您需要create APM wrappers around a TAP method

这并非完全直截了当,尤其是因为End*的{​​{1}}方法遵循APM模式。

要求和建议:

  • TokenProvider实施Task,因此您可以返回任务。
  • 必须从该任务的IAsyncResult属性返回state成员,因此您返回的任务不能是由IAsyncResult.AsyncState生成的任务 - 您必须通过async自己创建。
  • 操作完成时需要调用TaskCompletionSource<T>
  • 如果您覆盖callback,则必须也会覆盖匹配的Begin*

结果代码最终有点复杂。您可以使用我的AsyncEx.Tasks库中的End*来避免使用样板文件(目前,ApmAsyncFactory.ToBegin仅在prerelease build中):

ApmAsyncFactory

或者,如果你想看看如何制作香肠并手工完成,可以选择一种方法(记住所有例外情况都可以):

protected override IAsyncResult OnBeginGetToken(string appliesTo, string action,
    TimeSpan timeout, AsyncCallback callback, object state)
{
  return ApmAsyncFactory.ToBegin(GetCustomTokenAsync(appliesTo), callback, state);
}

protected override SecurityToken OnEndGetToken(IAsyncResult result,
    out DateTime cacheUntil)
{
  var ret = ApmAsyncFactory.ToEnd<SharedAccessSignatureToken>(result);
  cacheUntil = ...;
  return ret;
}

答案 1 :(得分:-3)

我根本不会使用IAsyncResult,而是应该返回Task<T>并等待它。您的GetCustomTokenAsync方法也是如此。