Ожидание завершения всех заданий с асинхронным ожиданием - PullRequest
0 голосов
/ 22 марта 2019

Я пытаюсь понять использование async-await в C # 5. Если у меня в методе запущено 2 задания, есть ли лучший способ дождаться их завершения в C # 5 +? Я сделал приведенный ниже пример, но мне не удалось увидеть, что здесь дает клавиатурная работа async await, кроме бесплатной документации с ключевым словом 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 голосов
/ 22 марта 2019

Вы запускаете задачи и просто забываете их, пока поток продолжает работать.Это исправляет это.

Main:

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

SomeWork:

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

More Изменение подписиWork:

private async Task MoreWork()

Очевидный запах кода, которыйдолжно помочь разобраться в проблеме с использованием async void.Если этого не требуется, этого всегда следует избегать.

При использовании async и await вы обычно захотите связать вызовы await с верхним уровнем (в данном случае Main).

await не является блокирующим, поэтому все, что вызывает метод async, должно действительно заботиться о возвращении Task.

...