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

luk*_*egf 2 c# asp.net async-await asp.net-web-api

所以,我有在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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

"消息": "发生了错误.", "ExceptionMessage": "一个或多个错误的发生.", "ExceptionType": "System.AggregateException", "堆栈跟踪":"在
System.Threading.Tasks.Task.ThrowIfExceptional (布尔includeTaskCanceledExceptions)
在System.Threading.Tasks.Task.Wait(的Int32 millisecondsTimeout,的CancellationToken的CancellationToken)
在System.Threading.Tasks.Task.Wait()
在MyController.WorkMethod(试验的TestObject)在MyController.cs:管线9
在lambda_method (封闭,对象,对象[])
在System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<> c__DisplayClass10.b__9(Object实例,对象[] methodParameters)
在System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute (Object实例,对象[]参数)
在System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext,IDictionary`2参数,的CancellationToken的CancellationToken)

输出如下:

WorkMethod -调用asyncMethod1之前
调用asyncMethod2前- asyncMethod1
调用DoAsyncWork2前- asyncMethod2
asyncMethod2 -将数据返回给呼叫方
asyncMethod1 -调用asyncMethod2后

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

Task.Run(async () => await this.asyncMethod1(asyncMethod1)).Wait();
Run Code Online (Sandbox Code Playgroud)

对此:

var task = this.asyncMethod1(asyncMethod1);

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

task.wait();
Run Code Online (Sandbox Code Playgroud)

我没有得到异常,但程序流程永远不会到达asyncMethod1中的位置,它会对asyncMethod2返回的响应执行一些操作.另外,输出如下:

WorkMethod - 在调用asyncMethod1
asyncMethod1之前- 在调用asyncMethod2 asyncMethod2之前 - 调用DoAsyncWork2
WorkMethod之前
- 调用asyncMethod1之后

这里有什么问题?我正在尝试实现的正确方法是什么,即从API控制器调用异步方法然后从第一个调用第二个异步方法?

Gab*_*uci 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();
}
Run Code Online (Sandbox Code Playgroud)

那样做那种方法毫无意义.您可以制作asyncMethod1实际的操作方法.如果你想.

也就是说,你得到的例外是因为实际上存在异常.但是因为你没有await得到结果,所以它会AggregateExceptionInnerExceptions集合中被抛出一个真正的异常.一旦你await的任务,你会看到抛出的真正的异常.