用异步等待功能等待所有作业完成

时间:2019-03-22 19:23:46

标签: c# asynchronous async-await

我试图了解C#5中async-await的用法。如果我有2种方法启动的作业,是否有最佳方法等待C#5 +中的作业完成?我已经完成了下面的示例,但是除了带有async关键字的免费文档之外,我看不到异步等待键将带来什么。

我举了下面的例子,我想“完成!”最后打印。但是事实并非如此。我错过了什么 ?如何使异步方法等待所有作业完成?在这里使用async-await有一点吗?我可以在这里使用非异步方法执行Task.WaitAll。我真的不明白,如果您想等待,异步会带来什么。

class Program
{
    static void Main(string[] args)
    {
        var fooWorker = new FooWorker();
        var barWorker = new BarWorker();
        var test = new Class1(fooWorker, barWorker);

        test.SomeWork();
        Console.ReadLine();
    }
}

public class Foo
{
    public Foo(string bar) => Bar = bar;
    public string Bar { get; }
}

public class Class1
{
    private IEnumerable<Foo> _foos;
    private readonly FooWorker _fooWorker;
    private readonly BarWorker _barWorker;

    public Class1(FooWorker fooWorker, BarWorker barWorker)
    {
        _fooWorker = fooWorker;
        _barWorker = barWorker;
    }

    public void SomeWork()
    {
        _foos = ProduceManyFoo();
        MoreWork();

        Console.WriteLine("FINISHED !");
    } 

    private async void MoreWork()
    {
        if (_foos == null || !_foos.Any()) return;

        var fooList = _foos.ToList();

        Task fooWorkingTask = _fooWorker.Work(fooList);
        Task barWorkingTask = _barWorker.Work(fooList);

        await Task.WhenAll(fooWorkingTask, barWorkingTask);
    }

    private IEnumerable<Foo> ProduceManyFoo()
    {
        int i = 0;
        if (++i < 100) yield return new Foo(DateTime.Now.ToString(CultureInfo.InvariantCulture));
    }
}

public abstract class AWorker
{
    protected virtual void DoStuff(IEnumerable<Foo> foos)
    {
        foreach (var foo in foos)
        {
            Console.WriteLine(foo.Bar);
        }
    }

    public Task Work(IEnumerable<Foo> foos) => Task.Run(() => DoStuff(foos));
}

public class FooWorker : AWorker { }
public class BarWorker : AWorker { }

1 个答案:

答案 0 :(得分:0)

在线程继续运行的同时,您正在解雇任务并忘记了它们。这样就可以解决。

主要:

static async Task Main(string[] args)
{
    var fooWorker = new FooWorker();
    var barWorker = new BarWorker();
    var test = new Class1(fooWorker, barWorker);
    await test.SomeWork();
    Console.ReadLine();
}

一些工作:

public async Task SomeWork()
{
    _foos = ProduceManyFoo();
    await MoreWork();
    Console.WriteLine("FINISHED !");
}

MoreWork签名更改:

private async Task MoreWork()

正在使用async void来消除明显的代码异味,这应该有助于弄清楚问题。除非有要求,否则应始终避免。

使用asyncawait时,通常需要将await调用链接到顶层(在这种情况下为Main)。

await是非阻塞的,因此任何调用async方法的人都应该真正关心返回的Task