gpt4 book ai didi

c# - 入口点可以在 CoreCLR 上用 'async' 修饰符标记吗?

转载 作者:太空狗 更新时间:2023-10-29 21:44:21 29 4
gpt4 key购买 nike

在 Stephan Cleary 最近关于 Async Console Apps on .NET CoreCLR 的博文中他向我们展示了在 CoreCLR(目前在 Visual Studio 2015,CTP6 上运行)中,入口点“Main”实际上可以标记为 async Task,正确编译并实际运行:

public class Program
{
public async Task Main(string[] args)
{
Console.WriteLine("Hello World");
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine("Still here!");
Console.ReadLine();
}
}

给出以下输出:

async Main entry point

ASP.NET 团队的博客文章 A Deep Dive into the ASP.NET 5 Runtime 加强了这一点:

In addition to a static Program.Main entry point, the KRE supports instance-based entry points. You can even make the main entry point asynchronous and return a Task. By having the main entry point be an instance method, you can have services injected into your application by the runtime environment.

我们知道到目前为止,An entry point cannot be marked with the 'async' modifier .那么,在新的 CoreCLR 运行时中,这实际上是如何实现的呢?

最佳答案

深入 CoreCLR 运行时的源代码,我们可以看到一个名为 RuntimeBootstrapper 的静态类,它负责调用我们的入口点:

public static int Execute(string[] args)
{
// If we're a console host then print exceptions to stderr
var printExceptionsToStdError = Environment.GetEnvironmentVariable(EnvironmentNames.ConsoleHost) == "1";

try
{
return ExecuteAsync(args).GetAwaiter().GetResult();
}
catch (Exception ex)
{
if (printExceptionsToStdError)
{
PrintErrors(ex);
return 1;
}

throw;
}
}

我们可以看到在内部,它调用了 ExecuteAsync(args).GetAwaiter().GetResult();,这在语义上等同于调用 Task.Result,除了我们收到的不是包装的 AggregationException,而是未包装的异常。

理解这一点很重要,因为没有“黑魔法”可以解释它是如何发生的。对于当前版本的 CoreCLR 运行时,该方法被允许标记为 async Task,因为它被运行时阻止在调用链的更高层。

旁注:

深入了解 ExecuteAsync,我们将看到它最终调用:

return bootstrapper.RunAsync(app.RemainingArguments);

When looking inside ,我们看到实际的 MethodInfo 调用我们的入口点:

public static Task<int> Execute(Assembly assembly, string[] args, IServiceProvider serviceProvider)
{
object instance;
MethodInfo entryPoint;

if (!TryGetEntryPoint(assembly, serviceProvider, out instance, out entryPoint))
{
return Task.FromResult(-1);
}

object result = null;
var parameters = entryPoint.GetParameters();

if (parameters.Length == 0)
{
result = entryPoint.Invoke(instance, null);
}
else if (parameters.Length == 1)
{
result = entryPoint.Invoke(instance, new object[] { args });
}

if (result is int)
{
return Task.FromResult((int)result);
}

if (result is Task<int>)
{
return (Task<int>)result;
}

if (result is Task)
{
return ((Task)result).ContinueWith(t =>
{
return 0;
});
}

return Task.FromResult(0);
}

关于c# - 入口点可以在 CoreCLR 上用 'async' 修饰符标记吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28938582/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com