Pouyan
Pouyan

Reputation: 2939

async method does not continue when await statement returns

I'm using MVC 4 and I have the following code :

    public void DoWork(string connectionId)
    {
        connectionId = this.connectionId;
        var a =  MakeADelayAsync();
    }

    public async Task MakeADelayAsync()
    {
        await Task.Delay(5000);
        var generalHubContext = GlobalHost.ConnectionManager.GetHubContext<GeneralHub>();
        generalHubContext.Clients.Client(connectionId).showNotification("Completed");
    }

"DoWork" method is my mvc action. what I intent to do is when the action button is pressed the "DoWork" calls an async method and returns to the client immediately. when the async method has completed his job it will notify client using signalR.

The problem is in the "MakeADelayAsync" method, those two lines after await won't be called ever. It seems that the flow never continues after await.

First question is Where is the problem in "MakeADelayAsync" ?

Second question is why do I have to write a useless code of var a = MakeADelayAsync(); to avoid compiler warning while I'm completely aware of what I am doing? I never use "a" anyway.

Upvotes: 3

Views: 948

Answers (2)

Stephen Cleary
Stephen Cleary

Reputation: 456417

"DoWork" method is my mvc action. what I intent to do is when the action button is pressed the "DoWork" calls an async method and returns to the client immediately. when the async method has completed his job it will notify client using signalR.

Doing this is extremely dangerous. I strongly recommend that you use a persistent queue, as I said in my previous answer: Azure queue, MSMQ, WebSphere MQ, etc.

However, if you insist on doing it the dangerous way, then you can use the code that I have on my blog to execute background work on ASP.NET outside of a request context:

public void DoWork(string connectionId)
{
    connectionId = this.connectionId;

    // This is extremely dangerous code! If ASP.NET unloads
    // your app, then MakeADelayAsync may not run to completion.
    BackgroundTaskManager.Run(() => MakeADelayAsync());
}

First question is Where is the problem in "MakeADelayAsync" ?

You're executing code that is attempting to resume on the request context after the request is completed and the request context is disposed. It's the same problem you had before.

Second question is why do I have to write a useless code of var a = MakeADelayAsync(); to avoid compiler warning while I'm completely aware of what I am doing?

The compiler warning is telling you that the code is almost certainly a mistake... and the compiler is right.

Upvotes: 1

yavuz
yavuz

Reputation: 332

can you try to mark your DoWork method as async?

public async void DoWork(string connectionId)
    {
        connectionId = this.connectionId;
        var a = MakeADelayAsync();
    }

Upvotes: 0

Related Questions