如何等待覆盖异步函数

本文关键字:覆盖 异步 函数 等待 何等待 | 更新日期: 2023-09-27 18:15:40

我们有一个通用的Job类,它有一个抽象的HeavyTask方法,像这样:

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; 
    }
}

和派生类覆盖HeavyTask函数,也使其异步:

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

那么当我们使用这种方法时,似乎没有等待HeavyTask():

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


全部完成JobFoo is Done

如果我们没有覆盖HeavyTaskasync,那么它是按预期工作的。但我不能保证那些推翻Job的人不会把HeavyTask变成async。我想知道为什么它没有被成功地等待,是否有一种方法可以确保它被等待?如果可以,您是否还可以解释是否像上面所示的那样将非异步函数重写为async是一种好做法?

如何等待覆盖异步函数

没有等待,因为没有可等待的(即Task)等待。该方法的返回类型为void。您应该避免在事件处理程序之外使用async void

如果你想让一个派生类使用async,让方法返回一个Task开始:

 protected abstract Task HeavyTaskAsync();

如果你需要有一个同步覆盖同步返回一个Task:

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

我不认为这一行是可等待的:

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

配偶在等什么?无返回值

怎么样
Task.Run(() => HeavyTask()).Wait();