Reputation: 33036
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
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
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