如何在例如Main()中调用async方法?

Lar*_*rry 58 c# asynchronous task async-await

public class test
{
    public async Task Go()
    {
        await PrintAnswerToLife();
        Console.WriteLine("done");
    }

    public async Task PrintAnswerToLife()
    {
        int answer = await GetAnswerToLife();
        Console.WriteLine(answer);
    }

    public async Task<int> GetAnswerToLife()
    {
        await Task.Delay(5000);
        int answer = 21 * 2;
        return answer;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我想在main()方法中调用Go,我该怎么做?我正在尝试c#新功能,我知道我可以将异步方法挂钩到事件并通过触发该事件,可以调用异步方法.

但是如果我想直接在main方法中调用它呢?我怎样才能做到这一点?

我做了类似的事情

class Program
{
    static void Main(string[] args)
    {
        test t = new test();
        t.Go().GetAwaiter().OnCompleted(() =>
        {
            Console.WriteLine("finished");
        });
        Console.ReadKey();
    }


}
Run Code Online (Sandbox Code Playgroud)

但似乎这是一个死锁,屏幕上没有任何内容.

Tim*_* S. 73

您的Main方法可以简化.对于C#7.1和更新版本:

static async Task Main(string[] args)
{
    test t = new test();
    await t.Go();
    Console.WriteLine("finished");
    Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)

对于早期版本的C#:

static void Main(string[] args)
{
    test t = new test();
    t.Go().Wait();
    Console.WriteLine("finished");
    Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)

这是async关键字(和相关功能)之美的一部分:回调的使用和混乱性质大大减少或消除.


arv*_*man 24

而不是等待,你最好new test().Go().GetAwaiter().GetResult() 不要使用, 因为这样可以避免异常被包装到AggregateExceptions中,所以你可以像往常一样用try catch(Exception ex)块来包围你的Go()方法.

  • @Ruchira,“等待”也会发生同样的情况。那么,当您没有 C# 7.1 或更高版本(其中“main”函数可以声明为“async”)时,应该如何解决问题呢? (2认同)

Dav*_*idG 18

由于C#v7.1 async main方法的发布已经可以使用,因此无需在已发布的答案中使用变通方法.添加了以下签名:

public static Task Main();
public static Task<int> Main();
public static Task Main(string[] args);
public static Task<int> Main(string[] args);
Run Code Online (Sandbox Code Playgroud)

这允许您编写如下代码:

static async Task Main(string[] args)
{
    await DoSomethingAsync();
}

static async Task DoSomethingAsync()
{
    //...
}
Run Code Online (Sandbox Code Playgroud)

  • 是的,我可以,谢谢。默认设置为“最新主要版本”,因此默认设置为7.0。我改为7.1,现在可以编译了。 (3认同)
  • 我正在尝试使用“静态异步任务Main(string [] args)”,但收到错误消息“ CS5001程序不包含适用于入口点的静态'Main'方法”。我已经检查了项目属性,并且下拉菜单中没有可用的启动对象。使用VS2017 + .NET Core 2.0的最新更新。我该如何克服呢? (2认同)

max*_*pan 9

class Program
{
    static void Main(string[] args)
    {
       test t = new test();
       Task.Run(async () => await t.Go());
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 此答案创建一个后台线程,如果前台线程先完成,则可能会导致问题 (2认同)

Muh*_*man 7

只要从返回的任务访问结果对象,就根本不需要使用GetAwaiter(仅在您访问结果时).

static async Task<String> sayHelloAsync(){

       await Task.Delay(1000);
       return "hello world";

}

static void main(string[] args){

      var data = sayHelloAsync();
      //implicitly waits for the result and makes synchronous call. 
      //no need for Console.ReadKey()
      Console.Write(data.Result);
      //synchronous call .. same as previous one
      Console.Write(sayHelloAsync().GetAwaiter().GetResult());

}
Run Code Online (Sandbox Code Playgroud)

如果您想等待任务完成并进行进一步处理:

sayHelloAsyn().GetAwaiter().OnCompleted(() => {
   Console.Write("done" );
});
Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)

如果您有兴趣从sayHelloAsync获取结果并对其进行进一步处理:

sayHelloAsync().ContinueWith(prev => {
   //prev.Result should have "hello world"
   Console.Write("done do further processing here .. here is the result from sayHelloAsync" + prev.Result);
});
Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)

最后一个等待功能的简单方法:

static void main(string[] args){
  sayHelloAsync().Wait();
  Console.Read();
}

static async Task sayHelloAsync(){          
  await Task.Delay(1000);
  Console.Write( "hello world");

}
Run Code Online (Sandbox Code Playgroud)


小智 5

public static void Main(string[] args)
{
    var t = new test();
    Task.Run(async () => { await t.Go();}).Wait();
}
Run Code Online (Sandbox Code Playgroud)

  • 在回答时,总是详细说明为什么它是所问问题的“答案”。 (5认同)