如何在ASP.NET Web API应用程序中从另一个方法调用一个异步方法

时间:2017-12-12 14:15:01

标签: c# asp.net asp.net-web-api async-await

所以我在ASP.NET Web API应用程序中使用异步方法有以下程序流程:API控制器调用异步方法(让我们称之为 asyncMethod1 ),这需要来自第二个异步的东西方法(我们称之为 asyncMethod2 )。 API控制器并不真正需要知道asyncMethod1何时完成,尽管为了给用户提供反馈会很好。另一方面,asyncMethod1确实需要知道asyncMethod2何时完成。

以下是相关代码:

public class MyController : ApiController
{
    private CustomClass customClass;

    public IHttpActionResult WorkMethod(TestObject testObject)
    {
        Debug.WriteLine("WorkMethod - before calling asyncMethod1");

        Task.Run(async () => await this.asyncMethod1(testObject)).Wait(); // ERROR HERE

        Debug.WriteLine("WorkMethod - after calling asyncMethod1");

        return Ok();
    }

    private async Task asyncMethod1(TestObject testObject)
    {
        Debug.WriteLine("asyncMethod1 - before calling asyncMethod2");

        Dictionary<string, string> x = await this.asyncMethod2(testObject);

        Debug.WriteLine("asyncMethod1 - after calling asyncMethod2");

        try
        {
            using (Task<IList<TestResponse>> testTask = customClass.DoAsyncWork1(x))
            {
                IList<TestResponse> response = await testTask;

                // Do something with response
                Debug.WriteLine("Transform 'response'");
            }
        }
        catch (Exception ex)
        {
            throw new Exception(" Exception ", ex);
        }
    }

    private async Task<Dictionary<string, string>> asyncMethod2(TestObject testObject)
    {
        try
        {
            Debug.WriteLine("asyncMethod2 - before calling DoAsyncWork2");

            using (Task<IList<SomeData>> workTask = customClass.DoAsyncWork2(testObject.x))
            {
                IList<SomeData> data = await workTask ;

                var output = new Dictionary<string, string>();
                output = data.values;

                Debug.WriteLine("asyncMethod2 - returning data to caller");

                return output;
            }
        }
        catch (Exception ex)
        {
            throw new Exception(" Exception ", ex);
        }
    }
}

CustomClass是我正在使用的自定义API中的一个类,其中 DoAsyncWork1 DoAsyncWork2 方法都是异步的。

当上面的代码运行时,我在方法 WorkMethod ,行Task.Run(async () => await this.asyncMethod1(testObject)).Wait();中得到以下异常:

  

“消息”:“发生了错误。”,“ExceptionMessage”:“发生了一个或多个错误。”,“ExceptionType”:“System.AggregateException”,“StackTrace”:“at

  System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
在System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout,CancellationToken cancellationToken)
在System.Threading.Tasks.Task.Wait()
在MyController.cs中的MyController.WorkMethod(Test testObject):第9行在lambda_method(Closure,Object,Object [])
在System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor 。&lt;&gt; c__DisplayClass10.b__9(Object instance,Object [] methodParameters)
在System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance,Object [] arguments)
在System .Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext,IDictionary`2 arguments,CancellationToken cancellationToken)

输出如下:

  

WorkMethod - 调用asyncMethod1之前的asyncMethod1 - 调用asyncMethod2之前
asyncMethod2 - 调用DoAsyncWork2之前
asyncMethod2 - 将数据返回给调用者asyncMethod1 - 调用asyncMethod2之后

如果在方法WorkMethod中我改变了这个:

Task.Run(async () => await this.asyncMethod1(asyncMethod1)).Wait();

到此:

var task = this.asyncMethod1(asyncMethod1);

Debug.WriteLine("WorkMethod - after calling asyncMethod1");

task.wait();

我没有例外,但是程序流程从未达到 asyncMethod1 的程度,它对 asyncMethod2 返回的响应有所帮助。此外,输出如下:

  

WorkMethod - 调用asyncMethod1之前的asyncMethod1 - 调用asyncMethod2之前的asyncMethod2 - 在调用DoAsyncWork2之前的工作方式
WorkMethod - 调用asyncMethod1之后

这是什么问题?执行我想要实现的目标的正确方法是什么,即从API控制器调用异步方法然后从第一个调用第二个异步方法?

1 个答案:

答案 0 :(得分:5)

你在评论中说:

  

在某个链上,你必须有一个非异步方法,   对不对?!

答案是否定的。一切都可以是异步的。所以你可以将此作为你的行动:

public async Tack<IHttpActionResult> WorkMethod(TestObject testObject)
{
    Debug.WriteLine("WorkMethod - before calling asyncMethod1");

    await this.asyncMethod1(testObject);

    Debug.WriteLine("WorkMethod - after calling asyncMethod1");

    return Ok();
}

那样做那种方法毫无意义。您可以将asyncMethod1设为实际操作方法。如果你想。

那就是说,你得到的例外是因为实际上存在异常。但是因为你没有await结果,它会被AggregateException抛出,InnerExceptions集合中有真正的异常。完成任务await后,您将看到抛出的真实异常。