独自の非同期メソッドを実装する最良の方法を知りたいです。この記事を読みましたが、同期メソッドをタスクにラップして非同期メソッドとして使用することはお勧めできません。この方法では他のスレッドを使用し、より多くのリソースを使用するためです。これは、use async で回避したいことです。 .
この記事では TaskCompletionSource を使用していますが、正確な使用方法はわかりません。TaskCompletionSource の目的はどれですか?
独自の非同期メソッドを実装する最良の方法を知りたいです。この記事を読みましたが、同期メソッドをタスクにラップして非同期メソッドとして使用することはお勧めできません。この方法では他のスレッドを使用し、より多くのリソースを使用するためです。これは、use async で回避したいことです。 .
この記事では TaskCompletionSource を使用していますが、正確な使用方法はわかりません。TaskCompletionSource の目的はどれですか?
async
メソッドを記述するのに最適なリソースは、 Stephen Toub による Task-based Asynchronous Pattern (TAP) ドキュメントです。そのドキュメントの情報の多くは、公式の MSDN ドキュメントの一部になりました。
短い (しかし完全な) チュートリアルが必要な場合は、私自身のasync
/await
イントロ ブログ投稿をお勧めします。他にもいくつかのチュートリアルがあります。について少し学んだらasync
、次の良いリソースは公式async
/ await
FAQです。
async
Channel9には素晴らしい動画がたくさんあります。彼らの多く (ほとんど?) はasync
、CTP がまだ CTP だった頃について話し合っていますが、製品化されたときの設計変更はほとんどありませんでした。
特定の質問に答えるために、既存の非同期操作 (I/O 操作、タイマー、イベントなど) のラッパーTaskCompletionSource
を作成するために使用されます。created byTask
でコードを実行することはできません。でコードを実行するために使用する必要があります。Task
TaskCompletionSource
Task.Run
Task
async
別のメソッド内で(.NET 5.0async
キーワードを使用して)メソッドを呼び出すことは問題ありません。あなたの質問を完全に理解しているかどうかはわかりませんが、次の簡単な例を見てください。開始とカウントの間の素数を表示するには、次のint
ように記述できます
async void DisplayPrimes()
{
int result = await GetPrimesCountAsync(2, 10000);
Console.WriteLine(result);
}
どこ
Task<int> GetPrimesCountAsync(int start, int count)
{
return Task.Run(() =>
ParrallelEnumerable.Range(start, count).COunt(n =>
Enumerable.Range(2, (int)Math.Sqrt(n) - 1).All(i => n % i > 0)));
}
ここで、async
修飾子は、そのメソッド内であいまいさが生じた場合に、await を識別子ではなくキーワードとして扱うようにコンパイラに指示します。これにより、識別子として await を使用する可能性のある C# 5.0 より前に記述されたコードが、エラーなしでコンパイルされることが保証されます。Task
async 修飾子は、 void または/を返すメソッドとラムダ式にのみ適用できますTask<TResult>
。
式に遭遇するとawait
、実行は (通常) 呼び出し元に戻りますyeild return
。イテレータの場合と同様です。ただし、戻る前に、ランタイムは待機中のタスクに継続をアタッチし、タスクが完了すると実行がメソッドに戻り、中断したところから続行されるようにします。コンパイラがそれを次のように変換するものを示す上記のメソッドを書くことができると思います
void DisplayPrimesCount()
{
var awaiter = GetPrimesCountAsync(2, 100000).GetAwaiter();
awaiter.OnCompleted(() =>
{
int result = awaiter.GetResult();
Console.WriteLine(result);
});
}
これが役立つことを願っています。
編集。したがって、タスクのブロックを回避するには (コードを投稿していないため、ケースが何であるかを判断するのは困難です)、async
作成するプロセスを「レベルアップ」する必要があります。
private async Task<bool> TestAsync()
{
return await Task.Run(() =>
{
// Do stuff non-blocking.
return true;
}).ConfigureAwait(continueOnCapturedContext:false);
}
TestAsync
ここでは、UI コンテキストではなく、スレッド プール スレッドで「return」ステートメントを実行することで完了することができます。これはすぐに呼び出し元に戻りますが、引き続き を使用するTask.Result
と、例外が にラップされ、AggregateException
それに応じて対処する必要があることに注意してください。
適切な説明は、MSDN の here にあります。async
/に入る前に、C# 4.0 タスクについて学習await
することをお勧めします。これにより、同時実行の理解が深まります。