Skip to content

The ApmAsyncFactory interop hangs if a path in async method returns synchronously. #281

@fiseni

Description

@fiseni

Hi,

I observed a strange behavior in ApmAsyncFactory. If the task contains a path that returns synchronously, then the execution hangs. It's easy to reproduce, so I'll just provide an example. I'll use asmx web service to demonstrate the issue.

public class DemoService : System.Web.Services.WebService
{

    [WebMethod]
    public IAsyncResult BeginRun(int option, AsyncCallback callback, object state)
    {
        return ApmAsyncFactory.ToBegin<string>(GetResponseAsync(option), callback, state);
    }
    [WebMethod]
    public string EndRun(IAsyncResult result)
    {
        return ApmAsyncFactory.ToEnd<string>(result);
    }

    private async Task<string> GetResponseAsync(int option)
    {
        if (option == 1)
        {
            await Task.Delay(1000);
            return "Works";
        }
        else if (option == 2)
        {
            // I tried awaiting a completed task too, just to test it out
            await Task.CompletedTask;
            return "Hangs";
        }
        else
        {
            return "Hangs";
        }
    }
}

To be sure that this is not a generic problem, I tried the solution provided in this article, and it works without issues.

public class DemoService : System.Web.Services.WebService
{

    [WebMethod]
    public IAsyncResult BeginRun(int option, AsyncCallback callback, object state)
    {
        return GetResponseAsync(option).AsApm(callback, state);
    }
    [WebMethod]
    public string EndRun(IAsyncResult result)
    {
        return ((Task<string>)result).Result;
    }

    private async Task<string> GetResponseAsync(int option)
    {
        if (option == 1)
        {
            await Task.Delay(1000);
            return "Works";
        }
        else if (option == 2)
        {

            await Task.CompletedTask;
            return "Works";
        }
        else
        {
            return "Works";
        }
    }
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions