所以我在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控制器调用异步方法然后从第一个调用第二个异步方法?
答案 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
后,您将看到抛出的真实异常。