可以将Response.OnStarting与异步等待一起使用吗?

时间:2019-01-14 17:46:09

标签: asp.net-core async-await asp.net-core-mvc

我想使用Response.OnStarting执行一些利用异步等待模式的代码。 Response.OnStarting方法定义为

 public void OnStarting(Func<Task> callback)

我经常看到它用来通过如下代码修改标头:

 context.Response.OnStarting( () => {
      //modify the headers or do some synchronous work
 });

但是我需要从OnStarting委托中进行一些异步工作。假设执行异步工作的方法声明如下:

 public Task DoWorkAsync() {

        //write to a db or do something else async

        return Task.CompletedTask;
 }

使用以下方法通过OnStarting委托调用此方法是否有效?

  context.Response.OnStarting(async () => {
       await DoWorkAsync();
  });

在Visual Studio中,它可以编译而不会发出警告,并且似乎可以正常工作。但是,对我来说,Response.OnStarting方法可用于进行同步和异步调用似乎很奇怪。有时,异步等待世界仍然让我有些挠头。您能否阐明这种方法是否有效以及为什么?为什么Response.OnStarting可以与同步和异步匿名方法一起使用(如果可以的话)?

更新
我做了一些挖掘,看是否可以找到调用委托传递给OnStarting方法的调用的代码。

我发现,DefaultHttpRespose对象包含OnStarting方法,并且在该方法内部它基本上称为IHttpResponseFeature.OnStarting,请参见此处:

 public override void OnStarting(Func<object, Task> callback, object state)
    {
        if (callback == null)
        {
            throw new ArgumentNullException(nameof(callback));
        }

        HttpResponseFeature.OnStarting(callback, state);
    }  

link to source code

但是有趣的是,我唯一能找到IHttpResponseFeature.OnStarting实现的地方是here,其代码如下:

 void IHttpResponseFeature.OnStarting(Func<object, Task> callback, object state)
    {
        var register = Prop<Action<Action<object>, object>>(OwinConstants.CommonKeys.OnSendingHeaders);
        if (register == null)
        {
            throw new NotSupportedException(OwinConstants.CommonKeys.OnSendingHeaders);
        }

        // Need to block on the callback since we can't change the OWIN signature to be async
        register(s => callback(s).GetAwaiter().GetResult(), state);
    }

但是该实现在异步委托调用上受阻。甚至对此有评论,但我不明白为什么这样做是必要的?而且我不确定这是IHttpResponseFeature.OnStarting的实现正在运行,这只是我在github上可以找到的唯一实现。任何帮助,不胜感激。

1 个答案:

答案 0 :(得分:2)

  

但是对我来说,Response.OnStarting方法可用于进行同步和异步调用都显得很奇怪。

必须同步实现 同步API。 Func<int> 必须返回int;它不能返回Task<int>

异步API可以异步实现Func<Task<int>>可能具有异步实现,返回的Task<int>将在将来完成。或者它可能具有同步实现,返回一个已经用Task<int>值完成的int

在处理异步API(包括接口和委托签名)时,完全允许同步实现。

我不会因阻塞实现而分心。该注释表明OWIN在应该是异步API的地方有一个同步API,而IHttpResponseFeature.OnStarting只是在向您隐藏这种怪异。