C# Main中的异步方法立即返回

C# Main中的异步方法立即返回,c#,.net-core,async-await,C#,.net Core,Async Await,在NetCore2.2应用程序中,我使用c#level 7.3实现了以下主要功能 public static async Task Main(string[] args) { _logger.TraceMethodBegins(nameof(Main)); AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException; TaskSche

在NetCore2.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));
    }
公共静态异步任务主(字符串[]args)
{
_TraceMethodBegins(name of(Main));
AppDomain.CurrentDomain.UnhandledException+=CurrentDomainOnUnhandledException;
TaskScheduler.UnobservedTaskeException+=TaskScheduleRonUnobservedTaskeException;
使用(ServiceFactory.Instance)
{
尝试
{
Parser.Default.ParseArguments(args)
.WithParsed(异步o=>
{
IWtgValuesCalculator wtgValuesCalculator=ServiceFactory.Instance.Kernel.Get();
等待wtgValuesCalculator.Calculate(o.StartDate、o.EndDate、o.FacilityName);
})
.WithNotParsed(异步o=>
{
//代码在这里输入
IWtgValuesCalculator wtgValuesCalculator=ServiceFactory.Instance.Kernel.Get();
等待wtgValuesCalculator.Calculate(null,null,null);
});
}
捕获(例外e)
{
_记录器。致命(e,e.Message);
}
}
//马上跳到这里,不用等待
_logger.TraceMethodds(名称(主要));
}
该方法立即返回,而不等待
wait wtgValuesCalculator.Calculate()
我已验证没有异常,如果我将其更改为使用所有同步方法,程序将按预期运行。另外,调用
wtgValueScalCalculator.Calculate(o.StartDate,o.EndDate,o.FacilityName).getWaiter().GetResult()使其正确运行。一位同事告诉我,他在某个地方读到,Main中的异步方法可能有问题,因为mscorlib没有完全加载,但我找不到任何关于它的信息。谁能给我们带来一些线索?

亲切的问候

您在传递给
WithParsed
WithNotParsed
的异步方法中等待。您不必在
async Main
方法中的任何地方等待

解析参数,然后等待wtgValuesCalculator。在Main中计算


换句话说:此时,您将两个异步方法发送到WithParsed/WithNotParsed,并在不等待Main的情况下继续。您的
wait
仅在WithParsed/WithNotParsed委托的上下文中使用。

每当出现wait时,您的方法将被分为2个部分:等待前和等待后(不是100%准确,但足够接近)。“第二个”方法将在等待的操作完成后执行,“第一个”部分将在等待的操作返回等待的操作时返回。
要使整个方法调用链等待“第二”部分,您需要对调用树上的每个可等待的方法进行等待。

如果这是为使用
async
而构建的,那么链在
ParseArguments
之后返回的任何内容都是可等待的。如果是这样的话,你会得到警告的。您的lambda几乎可以肯定正在有效地转换为某种
异步void
,因此无法判断它们何时完成。看起来您正在命中,这会调用您的委托,而不关心它是否是
等待
可能。@KirkLarkin有趣。。因此,如果我下载源代码并创建一个异步实现,我可以期望它能正常工作?理论上,是的,但与其派生一个现有的开源库,不如直接获取ParseArguments的结果并使用它,而不是使用WithParsed和WithNotParsed?