web-dev-qa-db-ja.com

非同期でタスクが返されるのを待つ

これがどういう意味で同期方式になるのか、誰かが説明できますか?メソッドをasyncに変更しようとすると、VSはそれについて文句を言います。

これは動作します:

public Task MethodName()
{
     return Task.FromResult<object>(null);
}

これはうまくいきません。

public async Task MethodName()
{
     return Task.FromResult<object>(null);
}

だから基本的に私はこれが正確に何を意味するのかを知りたいと思います:Task.FromResult<object>(null);

102
David Dury

asyncメソッドは通常のメソッドとは異なります。 asyncメソッドから返されるものはすべてTaskにラップされます。

値を返さない(void)場合はTaskにラップされ、intを返す場合はTask<int>にラップされます。

非同期メソッドがintを返す必要がある場合は、メソッドの戻り型をTask<int>としてマークし、Task<int>ではなくプレーンなintを返します。コンパイラはintTask<int>に変換します。

private async Task<int> MethodName()
{
    await SomethingAsync();
    return 42;//Note we return int not Task<int> and that compiles
}

同様に、Task<object>を返すとき、あなたのメソッドの戻り型はTask<Task<object>>であるべきです

public async Task<Task<object>> MethodName()
{
     return Task.FromResult<object>(null);//This will compile
}

あなたのメソッドはTaskを返しているので、どんな値も返してはいけません。そうでなければコンパイルされません。

public async Task MethodName()
{
     return;//This should work but return is redundant and also method is useless.
}

awaitステートメントのない非同期メソッドはasyncではないことに注意してください。

171

Asyncを使用し、関数の戻り型がgenericになる場合は、awaitキーワードを使用する必要があります。これは戻り値の例です。

public async Task<object> MethodName()
{
    return await Task.FromResult<object>(null);
}

これは戻り値のない例です。

public async Task MethodName()
{
    await Task.CompletedTask;
}

これらを読む:

TPL: http://msdn.Microsoft.com/ja-jp/library/dd460717(v = vs.110).aspx and Tasks: http://msdn.Microsoft。 com/ja-jp/library/system.threading.tasks(v = vs.110).aspx

非同期: http://msdn.Microsoft.com/ja-jp/library/hh156513.aspx お待ちください: http://msdn.Microsoft.com/ja-jp/library/) hh156528.aspx

38
Major

Asyncキーワードを追加することは、ステートマシンの作成を簡単にするための単なる構文糖です。要するに、コンパイラはあなたのコードを受け取ります。

public async Task MethodName()
{
     return null;
}

そしてそれをに変える。

public Task MethodName()
{
     return Task.FromResult<object>(null);
}

コードにawaitキーワードがある場合、コンパイラはそのメソッドを受け取り、それを実行に必要なステートマシンを表すクラスに変換する必要があります。それぞれのawaitキーワードで、変数の状態とスタックはクラスのフィールドに保存され、クラスはそれ自身をあなたが待っているタスクへの完了フックとして追加し、そして戻る。

そのタスクが完了すると、あなたのタスクは再び実行されます。そのため、変数の状態を復元してコードの次のスラブにジャンプするために、メソッドの先頭に追加のコードが追加されます。

厄介な例については、 async&awaitが何を生成するのか? を参照してください。

このプロセスは、コンパイラがyield文を使ってイテレータメソッドを処理する方法とよく似ています。

21
Jeremy Lakeman
    public static async Task<string> MyTask()
    {
        //C# anonymous AsyncTask
        return await Task.FromResult<string>(((Func<string>)(() =>
        {
            // your code here
            return  "string result here";

        }))());
    }
2
Adel Mourad