.NET Core是否支持异步控制台应用程序?

130

在某个时间点,CoreCLR支持异步的主入口点。见http://blog.stephencleary.com/2015/03/async-console-apps-on-net-coreclr.html

然而,下面这两个程序在.NET Core RTM中均无法工作。

using System;
using System.Threading.Tasks;

namespace ConsoleApplication
{
    public class Program
    {
        public static async Task Main(string[] args)
        {
            await Task.Delay(1000);
            Console.WriteLine("Hello World!");
        }
    }
}
或者
using System;
using System.Threading.Tasks;

namespace ConsoleApplication
{
    public class Program
    {
        public async Task Main(string[] args)
        {
            await Task.Delay(1000);
            Console.WriteLine("Hello World!");
        }
    }
}

这两个都会出现如下错误:

error CS5001:程序不包含适用于入口点的静态“Main”方法

.NET Core RTM支持异步控制台应用程序吗?


6
@svick 实际上,异步 Main 的支持已经在C# 7.1中添加了。请访问 https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7-1#async-main 。在您的Visual Studio 2017项目中,转到项目属性->构建->高级,然后将语言版本更改为7.1(或更高版本)。 - alv
1
请记得更改“属性->生成->高级->语言版本”以适用于Debug和Release构建类型,否则项目将在发布时失败。 - Mark
2
在我的项目中,如果我使用了Task而不是void,'async Main'才能正常工作。如果使用void,我会收到错误'CS5001'。 - Felipe Deveza
3个回答

189

是的,自从.NET Core 2.0以来,支持async Main函数。

dotnet --info
.NET Command Line Tools (2.0.0)

Product Information:
 Version:            2.0.0
 Commit SHA-1 hash:  cdcd1928c9

Runtime Environment:
 OS Name:     ubuntu
 OS Version:  16.04
 OS Platform: Linux
 RID:         ubuntu.16.04-x64
 Base Path:   /usr/share/dotnet/sdk/2.0.0/

Microsoft .NET Core Shared Framework Host

  Version  : 2.0.0
  Build    : e8b8861ac7faf042c87a5c2f9f2d04c98b69f28d

在C# 7.1版本中引入了对async Main函数的支持。然而,这个功能默认是不可用的。为了使用这个特性,你需要在.csproj文件中显式地指定使用C# 7.1版本。

<LangVersion>latest</LangVersion>

或通过

<LangVersion>7.1</LangVersion>
例如,针对 ASP.NET Core 2.0 项目:
<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <LangVersion>latest</LangVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
  </ItemGroup>
  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />
    <DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="2.0.0" />
  </ItemGroup>
</Project>

主函数可以重写如下:

using System.Threading.Tasks;

...
public static async Task Main(string[] args)
{
   await BuildWebHost(args).RunAsync();
}
...

参考资料:

  1. C# 7 系列之二:Async Main
  2. 拥护者 "Async Main" (C# 7.1)

6
在项目属性中,您还可以设置语言版本(现在?);构建->高级->语言版本。 - Nick
默认情况下,此选项的值为“最新主要版本”,等于7.0,而不是7.1!请手动更改。 - Eugene Hoza
1
第一个参考链接已失效,这是Wayback Machine的缓存链接:https://web.archive.org/web/20190118084407/https://blogs.msdn.microsoft.com/mazhou/2017/05/30/c-7-series-part-2-async-main/ - kristianp
1
链接失效了,因为显然微软员工需要手动迁移他们的博客:https://social.technet.microsoft.com/Forums/en-US/aeaa91cd-56ed-441f-8d22-ec0febfa8850/where-has-this-blog-gone?forum=tnwiki - kristianp

58

更新:C# 7.1原生支持异步主方法!请查看Evgeny在此处的回答

我将保留以下解决方法供后人参考,但现已不再需要。如果可以,请使用async main,它更简单易用!


以下是我在C# 7.1以下版本中首选的解决方法:

using System;
using System.Threading.Tasks;

namespace ConsoleApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            MainAsync(args).GetAwaiter().GetResult();

            Console.ReadKey();
        }

        public static async Task MainAsync(string[] args)
        {
            await Task.Delay(1000);
            Console.WriteLine("Hello World!");
        }
    }
}

GetAwaiter().GetResult().Wait(同步阻塞)相同,但更受欢迎,因为它展开了异常。


11

支持异步入口点的功能已经在一段时间前被删除。

请参见 aspnet/announcements github 上的此问题

我们决定与桌面CLR统一入口点语义。

RC1中已过时:

不再支持 async/Task<> Main。

不再支持实例化入口点类型(Program)。

Main方法应为public static void Main或public static int Main。

不再支持将依赖项注入到 Program 类构造函数和 Main 方法中。

改用 PlatformServices 和 CompilationServices。

要访问 IApplicationEnvironment、IRuntimeEnvironment、IAssemblyLoaderContainer、IAssemblyLoadContextAccessor、ILibraryManager, 请使用 Microsoft.Extensions.PlatformAbstractions.PlatformServices.Default 静态对象。

要访问 ILibraryExporter、ICompilerOptionsProvider,请使用 Microsoft.Extensions.CompilationAbstractions.CompilationServices.Default 静态对象。

不再支持 CallContextServiceLocator。改用 PlatformServices 和 CompilationServices。

同上。

这些将在 RC2 中被移除:#106


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接