Josh Darnell
I have an MVC 5 API controller running on .NET Framework 4.8 (you can find the full repro code [on GitHub](https://github.com/jadarnel27/AsyncVoidRaceConditionTest)), with the following `POST` method:
```
public IHttpActionResult Post([FromBody] string value)
{
bool result = RegularMethod();
return Json(result);
}
private bool RegularMethod()
{
AsyncVoidMethod();
return true;
}
private async void AsyncVoidMethod()
{
await Task.Delay(2000);
}
```
There is a bug here, in that I've accidentally written an `async void` method which isn't `await`ed. The result of that bug is that `AsyncVoidMethod()` is still running when the controller returns a 200 (success) response to the client (Google Chrome in this case).
The client code receives this success response, and makes a `PUT` request to the same API controller. That action method looks like this:
```
public void Put(int id, [FromBody] string value)
{
}
```
The client code looks like this (using jQuery 3.5.1):
```
$.ajax({
method: 'POST',
url: 'https://localhost:44334/api/values',
data: { value: "some thing" }
}).done(function () {
$.ajax({
method: 'PUT',
url: 'https://localhost:44334/api/values/5'
}).done(function () {
}).fail(function () {
$.ajax({
method: 'PUT',
url: 'https://localhost:44334/api/values/5'
}).done(function () {
})
});
}).fail(function (xhr, status, error) {
});
```
As mentioned, the initial `POST` request succeeds. But the first `PUT` request just kind of...hangs until the orphaned server-side task completes (two seconds later), and then gets an invalid response from the server (without ever running the `Put` action method):

You can see the two second pause on the `PUT` request in the screenshot above. If you're curious about what the response actually is, I grabbed it with Wireshark, and it's this HTML file:

The error makes sense (that's exactly what has happened), but I don't understand why the server sends it in response to this unrelated request.
The JavaScript code immediately retries the `PUT` request, which succeeds without issue.
**My question:** why is the first `PUT` request seemingly blocked by the orphaned task, and why does the server send that error page in response to this unrelated request?
I realize the easy solution is to not use `async void`, `await` that method call, and the problem is resolved. I'm curious about the underlying behavior that produces the strange results I've described though.
Additional information:
- If I shorten the delay (to 1 or 10 milliseconds), the `PUT` request succeeds some of the time (if the async task manages to get scheduled and complete before the second request is started)
- The same behavior occurs whether the server is running in local (full) IIS or IIS Express
- The errors vary - sometimes I get `ERR_METHOD_NOT_SUPPORTED` and other times I get `ERR_INVALID_HTTP_RESPONSE`
- The behavior appears to be client (or maybe protocol) specific
- Chrome (and Chromium-based Edge) both attempt http/2 and fail, and then revert to http/1.1 after a page refresh. They both exhibit the behavior described above
- IE 11 is able to use http/2, and both requests succeed
- This is a minimal repro of a real production scenario, in case that's important to anyone