最初に、いくつかの用語を明確にします。「非同期」(async
)は、開始前に呼び出しスレッドに制御を戻す可能性があることを意味します。async
方法、それらの「収率」点であるawait
式。
これは、MSDNのドキュメントで長年「バックグラウンドスレッドで実行する」という意味で(誤って)使用されている「非同期」という用語とは大きく異なります。
問題をさらに混乱させることasync
は、「待機可能」とは非常に異なります。いくつかあるasync
ではありませんawaitable型を返すその戻り値の型awaitableされていないメソッド、および多くの方法が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
式の中で "awaitables"に依存するようにすることです。これらの「待機可能物」は、他のasync
方法でも、待機可能物を返す通常の方法でもかまいません。返す正規の方法はTask
/ Task<T>
ことができます使用してTask.Run
バックグラウンドスレッドでコードを実行する、または(より一般的に)彼らが使用することができますTaskCompletionSource<T>
またはそのショートカット(の1 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
も非常に優れています。