繁体   English   中英

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

[英]How to call one async method from another one in ASP.NET Web API application

因此,我在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中的类,其中方法DoAsyncWork1DoAsyncWork2都是异步的。

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

“ Message”:“发生错误。”,“ ExceptionMessage”:“发生一个或多个错误。”,“ ExceptionType”:“ System.AggregateException”,“ StackTrace”:“在
System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
在System.Threading.Tasks.Task.Wait(Int32毫秒超时,CancellationToken cancelToken)
在System.Threading.Tasks.Task.Wait()
在MyController.cs:第9行的MyController.WorkMethod(Test testObject)中
在lambda_method(Closure,Object,Object [])
在System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor处。<> c__DisplayClass10.b__9(对象实例,对象[] methodParameters)
在System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute处(对象实例,Object []参数)
在System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext,IDictionary`2 arguments,CancellationToken cancelToken)

输出如下:

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控制器调用异步方法,然后从第一个方法调用第二个异步方法?

您在评论中说:

在链的某个点上,您必须有一个非异步方法,对吗?

答案是否定的。 一切都可以是异步的。 因此,您可以将其作为操作:

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任务后,您将看到抛出的实际异常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM