C# 如何在 Main 中调用异步方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13002507/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 01:18:00  来源:igfitidea点击:

How can I call an async method in Main?

c#asynchronousasync-awaittask

提问by Larry

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;
    }
}

if I want to call Go in main() method, how can I do that? I am trying out c# new features, I know i can hook the async method to a event and by triggering that event, async method can be called.

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

But what if I want to call it directly in main method? How can i do that?

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

I did something like

我做了类似的事情

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


}

But seems it's a dead lock and nothing is printed on the screen.

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

采纳答案by Tim S.

Your Mainmethod can be simplified. For C# 7.1 and newer:

你的Main方法可以简化。对于 C# 7.1 及更新版本:

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

For earlier versions of C#:

对于早期版本的 C#:

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

This is part of the beauty of the asynckeyword (and related functionality): the use and confusing nature of callbacks is greatly reduced or eliminated.

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

回答by arviman

Instead of Wait, you're better off using new test().Go().GetAwaiter().GetResult()since this will avoid exceptions being wrapped into AggregateExceptions, so you can just surround your Go() method with a try catch(Exception ex) block as usual.

最好不要使用 Wait, new test().Go().GetAwaiter().GetResult()因为这将避免将异常包装到 AggregateExceptions 中,因此您可以像往常一样用 try catch(Exception ex) 块包围 Go() 方法。

回答by Muhammad Soliman

As long as you are accessing the result object from the returned task, there is no need to use GetAwaiter at all (Only in case you are accessing the result).

只要您从返回的任务访问结果对象,就完全不需要使用 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());

}

if you want to wait for a task to be done and do some further processing:

如果你想等待一个任务完成并做一些进一步的处理:

sayHelloAsyn().GetAwaiter().OnCompleted(() => {
   Console.Write("done" );
});
Console.ReadLine();

If you are interested in getting the results from sayHelloAsync and do further processing on it:

如果您有兴趣从 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();

One last simple way to wait for function:

等待函数的最后一种简单方法:

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

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

}

回答by DavidG

Since the release of C# v7.1 asyncmainmethods have become available to use which avoids the need for the workarounds in the answers already posted. The following signatures have been added:

由于 C# v7.1asyncmain方法的发布已经可供使用,这避免了对已经发布的答案中的变通方法的需要。添加了以下签名:

public static Task Main();
public static Task<int> Main();
public static Task Main(string[] args);
public static Task<int> Main(string[] args);

This allows you to write your code like this:

这允许您像这样编写代码:

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

static async Task DoSomethingAsync()
{
    //...
}

回答by maxspan

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

回答by Sami Hussain

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

回答by Jean-Philippe

Use .Wait()

使用 .Wait()

static void Main(string[] args){
   SomeTaskManager someTaskManager  = new SomeTaskManager();
   Task<List<String>> task = Task.Run(() => marginaleNotesGenerationTask.Execute());
   task.Wait();
   List<String> r = task.Result;
} 

public class SomeTaskManager
{
    public async Task<List<String>> Execute() {
        HttpClient client = new HttpClient();
        client.BaseAddress = new Uri("http://localhost:4000/");     
        client.DefaultRequestHeaders.Accept.Clear();           
        HttpContent httpContent = new StringContent(jsonEnvellope, Encoding.UTF8, "application/json");
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        HttpResponseMessage httpResponse = await client.PostAsync("", httpContent);
        if (httpResponse.Content != null)
        {
            string responseContent = await httpResponse.Content.ReadAsStringAsync();
            dynamic answer = JsonConvert.DeserializeObject(responseContent);
            summaries = answer[0].ToObject<List<String>>();
        }
    } 
}

回答by Chitta

try "Result" property

尝试“结果”属性

class Program
{
    static void Main(string[] args)
    {
        test t = new test();
        t.Go().Result;
        Console.ReadKey();
    }
}