web-dev-qa-db-ja.com

c#「タスクメソッド」を「非同期」メソッドにすることもできますか?

私は新しい非同期CTPの要素を手に入れようとしているので、おそらくここで混乱しています。この「タスクメソッド」を問題なく使用できます。

    public static Task<String> LongTaskAAsync() {
        return Task.Run(() => {
            return("AAA");
            });
        }

しかし、別のタスクを実行するためにタスクが必要な場合は、それを「非同期」としてマークして「待機」を使用できますか?私はこれを試しました:

public async static Task<String> LongTaskAAsync() {
        await Task.Delay(2000);
        return Task.Run(() => {
            return("AAA");
            });
        }

しかし、不思議なことにこのコンパイラエラーが発生します。これは非同期メソッドであるため、戻り式はTask<string>ではなく 'string'型である必要があります

ここで何が欠けていますか?

23

私の async/await intro post を読むことをお勧めします。

asyncメソッドからの戻り値はTask<TResult>にラップされます。同様に、awaitはこれらの戻り値のラップを解除します。

public static async Task<String> LongTaskAAsync() {
  await Task.Delay(2000);
  return await Task.Run(() => {
    return("AAA");
  });
}

これの背後にある理由は、私の (非同期 "キーワードが機能する理由ThatWay"非公式FAQ )で説明されています。

追伸このような簡単なテストにはTask.FromResultを使用することもできます。

Edit:Taskオブジェクト自体を作成して返したい場合、メソッドはnotasyncになります。やや一般的なパターンの1つは、必要な場合にのみpublic部分を呼び出すasync non _asyncメソッドを使用することです。

たとえば、ある種の非同期キャッシュ-オブジェクトがキャッシュにある場合は、すぐに返します。それ以外の場合は、非同期で作成してキャッシュに追加し、それを返します(これはサンプルコードです-スレッドセーフではありません)。

public static Task<MyClass> GetAsync(int key)
{
  if (cache.Contains(key))
    return Task.FromResult(cache[key]);
  return CreateAndAddAsync(key);
}

private static async Task<MyClass> CreateAndAddAsync(int key)
{
  var result = await CreateAsync(key);
  cache.Add(key, result);
  return result;
}
18
Stephen Cleary

「タスクメソッド」を「非同期」メソッドにすることもできますか?

はい、可能です。メソッドのシグネチャをpublic async static Task<Task<String>> LongTaskAAsync()に変更するだけです。つまり、それが返すものだからです。

asyncキーワードを使用する場合、ランタイムは、非同期性を有効にするために、返される型をタスクにラップします。たとえば、stringを返す場合、ランタイムはそれをTask<string>にラップします。 intTask<int>に、Task<string>Task<Task<string>>に行きます。明確にするために、このコンソールアプリを参照してください。

public class Program
{
    public static void Main(string[] args)
    {
        // start the main procedure asynchron
        Task.Run(() => DoIt()).Wait();
    }

    // for async support since the static main method can't be async
    public static async void DoIt()
    {
        Program p = new Program();

        // use the methods
        string s = await p.GetString();
        int i = await p.GetInt();
        Task<string> tsk = await p.GetTaskOfString();

        // just to prove the task works:

        // C# 5
        string resultFromReturnedTask = await tsk;

        // C# 4
        string resultFromReturnedTask2 = tsk.Result;
    }

    public async Task<string> GetString()
    {
        return "string";
    }

    public async Task<int> GetInt()
    {
        return 6;
    }

    public async Task<Task<string>> GetTaskOfString()
    {
        return Task.Run(() => "string");
    }
}
3
GameScripting