私は 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.Run
UI スレッドをブロックしないように、メソッドを待機可能かつ非同期にするために、同期コードをラップする必要がありますか?
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
ブロックするのではなく、呼び出し元に制御を返すことができるメソッドを作成するにはどうすればよいか」である場合、答えはメソッドを宣言しasync
、await
その「制御」ポイントに使用することです。
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.Run
TaskCompletionSource<T>
TaskFactory.FromAsync
Task.FromResult
Task.Run
Task.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
も非常に優れています。