web-dev-qa-db-ja.com

非非同期メソッドで待機可能なメソッドを呼び出すことは可能ですか?

C#/ XAMLのWindows 8アプリケーションでは、非同期メソッドからawaitableメソッドを呼び出したい場合があります。

実際にこれを置き換えるのは正しいですか:

  public async Task<string> MyCallingMethod()
  {
      string result = await myMethodAsync();
      return result;
  }

これで :

   public string MyCallingMethod()
   {
       Task.Run(async () => {
            string result = await myMethodAsync();
            return result;
             });
   }

私にとっての利点は、待つことなくMyCallingMethodを使用できることですが、これは正しいですか?これは、非同期メソッドにrefパラメーターを持たせることができないため、MyCallingMethodのrefパラメーターを渡す場合に有利です。

29
Thomas Salandre

非同期ではない方法では、タスクを非同期的に開始し、結果を待つことはできません。

public void MyCallingMethod()
{
    Task t = myMethodAsync();
}

または、タスクの終了後に呼び出されるContinueWithイベントハンドラーをアタッチできます。

public void MyCallingMethod()
{
    myMethodAsync().ContinueWith(
        result =>
        {
            // do stuff with the result
        });
}

または、タスクから結果を同期的に取得できます。

public string MyCallingMethod()
{
    string result = myMethodAsync().Result;
    return result;
}
50
Martin Suchan

UIスレッドを使用している場合、そのようなことをしようとすべきではありません。スレッドをブロックすることになるからです。代わりに、refパラメーターを回避する必要があります。たとえば、変更する値を含む単純なクラス型のパラメーターを受け入れる必要があります。

これを行わないもう1つの理由は、ラムダがエンクロージングメソッドのrefパラメーターにアクセスできないため、refパラメーターを使用できないことです。

しかし、あなたが本当にこれをやりたいのなら(再び、あなたはすべきではないと本当に思う)、あなたはTaskの結果を得る必要があるでしょう。何かのようなもの:

public string MyCallingMethod()
{
    var task = Task.Run(async () =>
    {
        return await myMethodAsync();
    });
    return task.Result;
}
19
svick