Yuchen
Yuchen

Reputation: 33036

How to await for override async function?

We have a generic Job class which have an abstract HeavyTask method like this:

abstract class Job {
    private Task m_task; 
    protected abstract void HeavyTask(); 

    public void StartJob(){
        m_task = Task.Run(() => HeavyTask());
    }
    public async Task WaitJob(){
        await m_task; 
    }
}

And the derived class override the HeavyTask function and also make it async:

class JobFoo : Job {
    protected override async void HeavyTask()
    {
        await Task.Delay(1000);
        Debug.WriteLine("JobFoo is done");
    }
}

Then when we are using this method, it seems that the HeavyTask() is not awaited:

Job job = new JobFoo();
job.StartJob();
await job.WaitJob();
Debug.WriteLine("All Done");

Output:

All Done
JobFoo is Done

If we don't have async for the override HeavyTask, then it is working as expected. But I cannot guarantee those whose override the Job won't make the HeavyTask async. I want to understand why it is not awaited successfully and is there a way to make sure it will awaited? If you can, could you also explain whether it is a good practice to override a non-async function as async as shown above?

Upvotes: 4

Views: 6138

Answers (2)

Arman
Arman

Reputation: 885

I don't think this line is awaitable:

m_task = Task.Run(() => HeavyTask());

What is it spouse to wait for? No value is returned.

how about

Task.Run(() => HeavyTask()).Wait();

Upvotes: -3

i3arnon
i3arnon

Reputation: 116548

It's not awaited because there's no awaitable (i.e. Task) to await. That method has a void return type. And you should avoid using async void outside of event handlers.

If you want to enable a derived class to use async have the method return a Task to begin with:

 protected abstract Task HeavyTaskAsync();

And if you then need to have a synchronous override return a Task synchronously:

override Task HeavyTaskAsync()
{
    // do stuff;
    return Task.CompletedTask;
}

Upvotes: 11

Related Questions