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

时间:2012-10-21 21:45:03

标签: c# asynchronous

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

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

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

我做了类似

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


}

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

9 个答案:

答案 0 :(得分:61)

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

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

对于早期版本的C#:

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

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

答案 1 :(得分:24)

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

答案 2 :(得分: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);

这允许您编写如下代码:

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

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

答案 3 :(得分:8)

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

答案 4 :(得分:7)

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

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

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

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

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

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

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

}

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

command.ExecuteNonQuery()

答案 5 :(得分:1)

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

答案 6 :(得分:1)

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

答案 7 :(得分:0)

尝试“结果”属性

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

答案 8 :(得分:0)

C#9顶级语句进一步简化了事情,现在您甚至不必执行任何其他操作即可从async调用Main方法,您可以只需这样做:

using System;
using System.Threading.Tasks;

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

有关更多信息,请参见What's new in C# 9.0, Top-level statements

顶级语句可能包含异步表达式。在这种情况下,综合入口点将返回TaskTask<int>