简体   繁体   English

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

[英]How can I call an async method in Main?

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

But what if I want to call it directly in main method?但是如果我想直接在 main 方法中调用它呢? How can i do that?我怎样才能做到这一点?

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.但似乎这是一个死锁,屏幕上没有打印任何内容。

Your Main method can be simplified.您的Main方法可以简化。 For C# 7.1 and newer:对于 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 async keyword (and related functionality): the use and confusing nature of callbacks is greatly reduced or eliminated.这是async关键字(和相关功能)的美妙之处的一部分:回调的使用和混淆性质大大减少或消除。

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

Since the release of C# v7.1 async main methods have become available to use which avoids the need for the workarounds in the answers already posted.由于 C# v7.1 async main方法的发布已经可供使用,这避免了对已经发布的答案中的变通方法的需要。 The following signatures have been added:添加了以下签名:

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()
{
    //...
}
class Program
{
    static void Main(string[] args)
    {
       test t = new test();
       Task.Run(async () => await t.Go());
    }
}

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");

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

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

try "Result" property尝试“结果”属性

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

C# 9 Top-level statements simplified things even more, now you don't even have to do anything extra to call async methods from your Main , you can just do this: C# 9 顶级语句进一步简化了事情,现在你甚至不需要做任何额外的事情来从Main调用async方法,你可以这样做:

using System;
using System.Threading.Tasks;

await Task.Delay(1000);
Console.WriteLine("Hello World!");

For more information see What's new in C# 9.0, Top-level statements :有关更多信息,请参阅C# 9.0 中的新增功能,顶级语句

The top-level statements may contain async expressions.顶级语句可能包含异步表达式。 In that case, the synthesized entry point returns a Task , or Task<int> .在这种情况下,合成入口点返回一个TaskTask<int>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM