非同期にするには、メソッドに Task.Run を配置する必要がありますか? 質問する

非同期にするには、メソッドに Task.Run を配置する必要がありますか? 質問する

私は async await を最も単純な形で理解しようとしています。この例では、2 つの数値を追加する非常に単純なメソッドを作成したいと思います。もちろん、処理時間はまったくかかりませんが、ここで例を定式化するだけです。

例1

private async Task DoWork1Async()
{
    int result = 1 + 2;
}

例2

private async Task DoWork2Async()
{
    Task.Run( () =>
    {
        int result = 1 + 2;
    });
}

await を実行すると、DoWork1Async()コードは同期的に実行されますか、それとも非同期的に実行されますか?

Task.RunUI スレッドをブロックしないように、メソッドを待機可能かつ非同期にするために、同期コードをラップする必要がありますか?

Task私のメソッドがまたは を返す場合、非同期にするためTask<T>にコードを でラップする必要があるかどうかを調べようとしていますTask.Run

ネット上では、 async がまったくなく、 または でラップされていないコードを待っている例を目にしTask.RunますStartNew

ベストアンサー1

まず、いくつかの用語を明確にしましょう。「非同期」( async) は、開始前に呼び出しスレッドに制御を渡す可能性があることを意味します。メソッドではasync、これらの「譲歩」ポイントは式ですawait

これは、MSDN ドキュメントで長年「バックグラウンド スレッドで実行される」という意味で (誤って) 使用されてきた「非同期」という用語とはまったく異なります。

さらに問題を複雑にしているのは、asyncは「待機可能」とは大きく異なるということです。戻り値の型が待機可能でないメソッドがいくつかありasync、待機可能な型を返すが待機可能でないメソッドも多数ありますasync

それが何でないかはもう十分です。それが何であるかを次に示します。

  • キーワードasyncは非同期メソッドを許可します (つまり、await式を許可します)。asyncメソッドはTask、、、Task<T>または (必要な場合)を返すことができますvoid
  • 特定のパターンに従う型はすべて待機可能です。最も一般的な待機可能な型はTaskと ですTask<T>

したがって、質問を「待機可能な方法でバックグラウンド スレッドで操作を実行するにはどうすればよいか」と言い換えると、答えは次のようになりますTask.Run

private Task<int> DoWorkAsync() // No async because the method does not need await
{
  return Task.Run(() =>
  {
    return 1 + 2;
  });
}

(ただし、このパターンは不適切なアプローチです。以下を参照してください)。

しかし、質問が「asyncブロックするのではなく、呼び出し元に制御を返すことができるメソッドを作成するにはどうすればよいか」である場合、答えはメソッドを宣言しasyncawaitその「制御」ポイントに使用することです。

private async Task<int> GetWebPageHtmlSizeAsync()
{
  var client = new HttpClient();
  var html = await client.GetAsync("http://www.example.com/");
  return html.Length;
}

asyncしたがって、基本的なパターンは、式の中で「待機可能」に依存するコードを持つことですawait。これらの「待機可能」は、他のasyncメソッド、または待機可能を返す通常のメソッドにすることができます。 / を返す通常のメソッドはTaskバックグラウンド スレッドでコードを実行するために を使用するか、(より一般的には)またはそのショートカットの 1 つ ( 、など) を使用できます。メソッド全体を でラップすることはお勧めしません。同期メソッドには同期シグネチャが必要であり、 でラップするかどうかはコンシューマーに任せる必要があります。Task<T> Task.RunTaskCompletionSource<T>TaskFactory.FromAsyncTask.FromResultTask.RunTask.Run

private int DoWork()
{
  return 1 + 2;
}

private void MoreSynchronousProcessing()
{
  // Execute it directly (synchronously), since we are also a synchronous method.
  var result = DoWork();
  ...
}

private async Task DoVariousThingsFromTheUIThreadAsync()
{
  // I have a bunch of async work to do, and I am executed on the UI thread.
  var result = await Task.Run(() => DoWork());
  ...
}

を持っていますasync/awaitイントロ私のブログの最後には、いくつかの優れたフォローアップ リソースがあります。の MSDN ドキュメントasyncも非常に優れています。

おすすめ記事