简体   繁体   English

在 Web API 中使用异步等待时出现 500 内部服务器错误

[英]500 internal server error while using async await in web API

I've a web API on server side as below.我在服务器端有一个 Web API,如下所示。 It is using async-await pattern.它使用异步等待模式。 All these methods are present inside MyClassController class所有这些方法都存在于MyClassController类中

[Route("install")]
public async Task<IHttpActionResult> InstallProduct()
{ 
   Log("milestone1");
   Install();
   Log("milestone6");
}

private bool Install()
{
   MyClass.Register();        
   Log("milestone5");
}

private static async void Register()
{
    Log("milestone2");
    using (HttpClientHandler handler = new HttpClientHandler())
    {
        using (var client = new HttpClient(handler))
        {
            var method = "http://BaseUrlOfWebsite#2/api/applications";
            using (MultipartFormDataContent form = new MultipartFormDataContent())
            {
                //make POST API call into website # 2
                var response = await client.PostAsync(method, form);
                Log("milestone3");
            }
       }
   }
   Log("milestone4");
}

Overall call is like this:整体调用是这样的:

Client code -> install API on website # 1 -> applications API on website # 2客户端代码 -> 在网站 #1 上install API -> 在网站 #2 上install applications API

My expected log statements are in below order:我预期的日志语句按以下顺序排列:

milestone1
milestone2
milestone3
milestone4
milestone5
milestone6

Actual log order that I see in log files is as below:我在日志文件中看到的实际日志顺序如下:

milestone1
milestone2
milestone5
milestone6
milestone3
milestone4

Code doesn't causes error anywhere but it returns 500 internal server error code to calling client.代码不会在任何地方导致错误,但它会向调用客户端返回 500 内部服务器错误代码。 I've two questions here:我在这里有两个问题:

  1. Why the logs are not as per my expectation?为什么日志不符合我的预期? My understanding is that Register method should get blocked while calling external website as I'm using await while waiting for response.我的理解是Register方法应该在调用外部网站时被阻止,因为我在等待响应时使用await
  2. Can this out of order code execution cause 500 internal server error even though my code isn't throwing any error?即使我的代码没有抛出任何错误,这种乱序代码执行是否会导致 500 内部服务器错误?

Note : Same logs get printed in expected order when I debug the install API with debugger attached in Visual Studio.注意:当我使用 Visual Studio 中附加的调试器调试install API 时,会按预期顺序打印相同的日志。

Update : If I make the call to external website client.PostAsync run synchronously forcefully using Task.Run then I get 200 OK response.更新:如果我调用外部网站client.PostAsync使用Task.Run强制同步运行,那么我会得到 200 OK 响应。 Why web API results in error if I can fire and forget the call to external website and my remaining code can run synchronously to finish the web API call.如果我可以触发并忘记对外部网站的调用,并且我的剩余代码可以同步运行以完成 Web API 调用,那么为什么 Web API 会导致错误。

Register method is async, it returns void, instead of Task, which could be awaited. Register方法是异步的,它返回void,而不是可以等待的Task。 And instead of awaiting for task your code is running synchronously.而不是等待任务你的代码同步运行。

    [Route("install")]
        public async Task<IHttpActionResult> InstallProduct()
        {
            Log("milestone1");
            await Install();
            Log("milestone6");
        }

        private async Task Install()
        {
            await MyClass.Register();

            Log("milestone5");
        }

        private static async Task Register()
        {
            Log("milestone2");
            using (var handler = new HttpClientHandler())
            {
                using (var client = new HttpClient(handler))
                {
                    var method = "http://BaseUrlOfWebsite#2/api/applications";
                    using (MultipartFormDataContent form = new MultipartFormDataContent())
                    {
                        //make POST API call into website # 2
                        var response = await client.PostAsync(method, form);
                        Log("milestone3");
                    }
                }
            }
            Log("milestone4");
        }

In general, when you see async void in your code it's bad news, because:通常,当您在代码中看到 async void 时,这是个坏消息,因为:

you can't wait for its completion (as mentioned in this post already) any unhandled exceptions will terminate your process (ouch!)你不能等待它的完成(如这篇文章中已经提到的)任何未处理的异常都会终止你的进程(哎哟!)

Suppose you have a timer event that fires every once in a while and you want to do some asynchronous processing inside the handler, so you proceed to write something along the lines of:假设您有一个每隔一段时间触发一次的计时器事件,并且您想在处理程序中进行一些异步处理,因此您继续编写以下内容:

var timer = new Timer();
timer.Elapse += OnTimerFired;
timer.Interval = 1000;
timer.Start();

... ...

private static async void Register()
{
   await Task.Delay(1000);

   // this is going to terminate your process!
   throw new Exception();
}

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

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