Home > Net >  Unable to Intentionally Trigger Async Deadlock
Unable to Intentionally Trigger Async Deadlock

Time:09-17

I'm trying to confirm that a library I wrote will not cause an asychronous deadlock. To do that, I'm first trying to intentionally cause one (so that I can replace the innermost call with a call to my library), but no matter what I do, no deadlock occurs... what am I misunderstanding?

I've setup the relevant code in a new api (because I thought that apis were non-reentrant/single-threaded) and just in case it matters, I've moved each function to its own class and added Thread.Sleep commands to ensure that there is activity in each method both before and after the await.


    public class TestingController : ApiController
    {
        [HttpPost]
        [Route("api/Testing/TriggerAsyncDeadlock")]
        [ResponseType(typeof(string))]
        public HttpResponseMessage TriggerAsyncDeadlock()
        {
            return Request.CreateResponse(HttpStatusCode.OK, new AsyncCaller().CallerAsync().Result);
        }
    }


    public class AsyncBase
    {
        public async Task<string> BaseAsync()
        {
            Thread.Sleep(500);
            var ret = await Task.FromResult("Result");
            Thread.Sleep(500);
            return ret;
        }
    }
    public class AsyncCaller
    {
        public async Task<string> CallerAsync()
        {
            Thread.Sleep(500);
            var ret = "These are the results: ";
            var asyncBase = new AsyncBase();
            for (var i = 1; i < 5; i  )
            {
                ret  = $"'{await asyncBase.BaseAsync()}',";
                Thread.Sleep(500);
            }
            return ret.Substring(0, ret.Length - 1);
        }
    }

Edit: I'm running .net framework 4.7.1

CodePudding user response:

If you mean this kind of deadlock, then it requires these things to be present:

  1. A context that only allows one thread at a time. If your code is ASP.NET, then it has a context like this. ASP.NET Core doesn't, and thus isn't subject to this kind of deadlock.
  2. Code that blocks in this context waiting for an an asynchronous continuation to complete.
  3. An asynchronous continuations that needs to enter the context in order to complete.

In this case, you don't have any asynchronous continuations. await Task.FromResult("Result") is literally just a less-efficient form of "Result" - i.e., no asynchronous work is being done. The code is always fully synchronous.

In order to cause this kind of deadlock (assuming you're running on ASP.NET pre-Core where this kind of deadlock is possible), you need to replace Thread.Sleep with await Task.Delay. That way the code will actually run asynchronously.

  • Related