ChatGPT解决这个技术问题 Extra ChatGPT

在 C# 的控制台应用程序中使用“异步”[重复]

这个问题在这里已经有了答案:Can't specify the 'async' modifier on the 'Main' method of a console app (18 answers) Closed 5 years ago。

我有这个简单的代码:

public static async Task<int> SumTwoOperationsAsync()
{
    var firstTask = GetOperationOneAsync();
    var secondTask = GetOperationTwoAsync();
    return await firstTask + await secondTask;
}


private async Task<int> GetOperationOneAsync()
{
    await Task.Delay(500); // Just to simulate an operation taking time
    return 10;
}

private async Task<int> GetOperationTwoAsync()
{
    await Task.Delay(100); // Just to simulate an operation taking time
    return 5;
}

伟大的。这编译。

但是假设我有一个控制台应用程序并且我想运行上面的代码(调用 SumTwoOperationsAsync())。

static void Main(string[] args)
{
     SumTwoOperationsAsync();
}

但我已经读过(使用 sync 时)我必须一直同步 updown

这是否意味着我的 Main 函数应标记为 async

嗯,不可能是因为有编译错误:

入口点不能用“异步”修饰符标记

如果我理解异步内容,线程将进入 Main 函数 → SumTwoOperationsAsync → 将调用这两个函数并退出。但直到 SumTwoOperationsAsync

我错过了什么?

@nawful 似乎错过了关键链接,所以这里是... docs.microsoft.com/en-us/dotnet/csharp/whats-new/… - 在您的 Visual Studio 2017 项目中,转到项目属性 ->构建->高级,然后将您的语言版本更改为 7.1(或更高版本)

S
Stephen Cleary

在大多数项目类型中,您的 async“向上”和“向下”将在 async void 事件处理程序处结束,或者将 Task 返回到您的框架。

但是,控制台应用程序不支持此功能。

您可以对返回的任务执行 Wait

static void Main()
{
  MainAsync().Wait();
  // or, if you want to avoid exceptions being wrapped into AggregateException:
  //  MainAsync().GetAwaiter().GetResult();
}

static async Task MainAsync()
{
  ...
}

或者您可以use your own context like the one I wrote

static void Main()
{
  AsyncContext.Run(() => MainAsync());
}

static async Task MainAsync()
{
  ...
}

async 控制台应用程序的更多信息是 on my blog


如果它是 not 控制台应用程序,我的观察(问题的最后一行)是否正确?线程停止在 SumTwoOperationsAsync ...对吗? (假设 Main 调用方法未标记为异步)
我有一个 intro on my blog,它解释了线程如何通过“上下文”与 async 一起工作。
重新阅读您的答案-您是说在控制台应用程序中使用异步毫无意义吗?
@RoyiNamir:不。不过,它并不常见,除非您使用的是仅异步 API。控制台(和其他桌面)应用程序通常不太关心浪费线程。
@user2173353:不,它肯定会被 catch 捕获。如果这不是您所看到的,我建议您使用最小的代码示例提出您自己的问题。
M
Murilo Maciel Curti

这是最简单的方法

static void Main(string[] args)
{
    Task t = MainAsync(args);
    t.Wait();
}

static async Task MainAsync(string[] args)
{
    await ...
}

A
Alberto

作为一种快速且范围广泛的解决方案:

Task.Result

Task.Result 和 Task.Wait 在与 I/O 一起使用时都不允许提高可伸缩性,因为它们会导致调用线程保持阻塞等待 I/O 结束。

当您在不完整的任务上调用 .Result 时,执行该方法的线程必须坐下来等待任务完成,这会阻止线程同时执行任何其他有用的工作。这否定了任务的异步性质的好处。

notasync


R
Richard Keene

我的解决方案。 JSONServer 是我为在控制台窗口中运行 HttpListener 服务器而编写的一个类。

class Program
{
    public static JSONServer srv = null;

    static void Main(string[] args)
    {
        Console.WriteLine("NLPS Core Server");

        srv = new JSONServer(100);
        srv.Start();

        InputLoopProcessor();

        while(srv.IsRunning)
        {
            Thread.Sleep(250);
        }

    }

    private static async Task InputLoopProcessor()
    {
        string line = "";

        Console.WriteLine("Core NLPS Server: Started on port 8080. " + DateTime.Now);

        while(line != "quit")
        {
            Console.Write(": ");
            line = Console.ReadLine().ToLower();
            Console.WriteLine(line);

            if(line == "?" || line == "help")
            {
                Console.WriteLine("Core NLPS Server Help");
                Console.WriteLine("    ? or help: Show this help.");
                Console.WriteLine("    quit: Stop the server.");
            }
        }
        srv.Stop();
        Console.WriteLine("Core Processor done at " + DateTime.Now);

    }
}