0

Given the following code:

    public async Task Send() // part of Sender class
    {
          // sync code
    }

    // // 

    private async Task HandleMessage()
    {
        // await sender.Send(); // exits HandleMessage immediately
        sender.Send().Wait(); // works as expected, waiting to complete
        DoOtherStuff(); // doesn't get hit with await
        return;
    }

    RunRecurringTask(async () => await HandleMessage(), result);

    public void RunRecurringTask(Action action, RecurringTaskRunResult result)
    {
            action();
            result.DoStuff();
    }

I thought that await tells the thread to come back when the awaited thing is complete, but it looks like for some reason that's not happening: the remaining code is never hit and everything just... stops. What could be causing this?

This is a console application in an Azure WebJob, for what it's worth. When Wait is used, I get the expected results, however with await, the job just completes.

SB2055
  • 12,272
  • 32
  • 97
  • 202
  • 1
    When `async` method find `await`, it will then delegate method execution to another thread, and method returns immediately. When method execution finished, it will comeback to execute the rest of the method. – Niyoko Nov 04 '16 at 03:38
  • @NiyokoYuliawan in my case, I want the webjob to continue running (not to report "completed") until all of the work is finished. The behavior I'm seeing is that `DoOtherStuff` never gets logged to the webjob, unless I use `Wait` – SB2055 Nov 04 '16 at 03:41
  • If you are using webjobs your question is a duplicate of http://stackoverflow.com/questions/22916325/azure-webjobs-can-i-use-async-methods Please include the code that calls `HandleMessage`, that is likely where your problem is. – Scott Chamberlain Nov 04 '16 at 03:43
  • @ScottChamberlain updated – SB2055 Nov 04 '16 at 03:47

1 Answers1

3

You should never do async void unless you are writing a event handler. A Action with the async modifier is a async void method. You need to make the argument a Func<Task> and then do await action() in your RunRecurringTask

private async Task HandleMessage()
{
    await sender.Send();
    DoOtherStuff();
    return;
}

RunRecurringTask(async () => await HandleMessage(), result);
//You also could do 
//RunRecurringTask(() => HandleMessage(), result);

public async Task RunRecurringTask(Func<Task> action, RecurringTaskRunResult result)
{
        await action();
        result.DoStuff();
}

If you had other methods that where not marked with async you will need to change all of them up the call stack till you get to the entry point from the SDK. The SDK understands how to handle functions with a async Task return type since the 0.4.0-beta version.

Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431