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


}

しかし、それはデッドロックのようで、画面には何も印刷されません。

4

9 に答える 9

128

あなたの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キーワード(および関連する機能)の美しさの一部です。コールバックの使用と混乱を招く性質が大幅に削減または排除されます。

于 2012-10-22T00:07:51.587 に答える
28

Waitの代わりに使用する方が良いでしょう。 new test().Go().GetAwaiter().GetResult() これにより、例外がAggregateExceptionsにラップされるのを回避できるため、通常どおり、Go()メソッドをtry catch(Exception ex)ブロックで囲むことができます。

于 2016-03-08T11:01:00.233 に答える
26

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()
{
    //...
}
于 2017-07-28T08:49:57.537 に答える
15
class Program
{
    static void Main(string[] args)
    {
       test t = new test();
       Task.Run(async () => await t.Go());
    }
}
于 2017-12-06T01:19:42.360 に答える
13

返されたタスクから結果オブジェクトにアクセスしている限り、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());

}

タスクが完了するのを待ち、さらに処理を行う場合:

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

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

関数を待つ最後の簡単な方法:

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

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

}
于 2017-06-26T19:55:38.663 に答える
5
public static void Main(string[] args)
{
    var t = new test();
    Task.Run(async () => { await t.Go();}).Wait();
}
于 2018-04-07T15:09:33.590 に答える
2

.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>>();
        }
    } 
}
于 2018-07-20T14:35:05.837 に答える
0

「結果」プロパティを試してください

class Program
{
    static void Main(string[] args)
    {
        test t = new test();
        t.Go().Result;
        Console.ReadKey();
    }
}
于 2020-02-13T05:16:30.050 に答える
0

C#9トップレベルのステートメントは、物事をさらに簡素化しました。今では、asyncからメソッドを呼び出すために特別なことをするMain必要はありません。これを行うだけです。

using System;
using System.Threading.Tasks;

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

詳細については、C#9.0の新機能、トップレベルのステートメントを参照してください。

トップレベルのステートメントには、非同期式が含まれる場合があります。その場合、合成されたエントリポイントは、、Taskまたはを返しますTask<int>

于 2020-11-21T21:29:38.980 に答える