Асинхронный метод в Main немедленно возвращается - PullRequest
0 голосов
/ 14 января 2019

У меня есть следующее Main в приложении net core 2.2, используя c # level 7.3

    public static async Task Main(string[] args)
    {
        _logger.TraceMethodBegins(nameof(Main));
        AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
        TaskScheduler.UnobservedTaskException += TaskSchedulerOnUnobservedTaskException;
        using (ServiceFactory.Instance)
        {
            try
            {
                Parser.Default.ParseArguments<Options>(args)
                    .WithParsed(async o =>
                    {
                        IWtgValuesCalculator wtgValuesCalculator = ServiceFactory.Instance.Kernel.Get<IWtgValuesCalculator>();
                        await wtgValuesCalculator.Calculate(o.StartDate, o.EndDate, o.FacilityName);
                    })
                    .WithNotParsed(async o =>
                    {
//Code enters over here
                        IWtgValuesCalculator wtgValuesCalculator = ServiceFactory.Instance.Kernel.Get<IWtgValuesCalculator>();
                        await wtgValuesCalculator.Calculate(null, null, null);
                    });
            }
            catch (Exception e)
            {
                _logger.Fatal(e, e.Message);
            }
        }
//And jump here immediately without awaiting
        _logger.TraceMethodEnds(nameof(Main));
    }

Метод возвращается немедленно, не ожидая await wtgValuesCalculator.Calculate() Я проверил, что исключений нет, если я изменю его на все методы синхронизации, программа будет работать, как и ожидалось. Кроме того, вызов wtgValuesCalculator.Calculate(o.StartDate, o.EndDate, o.FacilityName).GetAwaiter().GetResult(); заставит его работать правильно. Коллега сказал мне, что он где-то читал, что асинхронные методы в Main могут иметь проблемы, потому что mscorlib не был полностью загружен, но я не могу найти информацию об этом. Кто-нибудь может пролить свет на это? С уважением.

Ответы [ 2 ]

0 голосов
/ 15 января 2019

Всякий раз, когда появляется ожидание, ваш метод разделяется на 2: до ожидания и после ожидания (это не на 100% точно, но достаточно близко). «Второй» метод будет выполнен после завершения ожидаемой операции, а «первая» часть возвращается, когда ожидаемая операция возвращает ожидаемое. Чтобы вся цепочка вызовов метода дожидалась «вторых» частей, вам нужно иметь ожидание для каждого ожидаемого метода в дереве вызовов.

0 голосов
/ 14 января 2019

Вы ожидаете в асинхронных методах, которые вы передаете WithParsed и WithNotParsed. Вы не ждете нигде внутри вашего async Main метода.

Разобрать ваши аргументы и затем await wtgValuesCalculator.Calculate внутри Main.

Другими словами: в данный момент вы отправляете два асинхронных метода в WithParsed / WithNotParsed и продолжаете, не ожидая в Main. Ваш await только в контексте делегатов WithParsed / WithNotParsed.

...