3

独自の非同期メソッドを実装する最良の方法を知りたいです。この記事を読みましたが、同期メソッドをタスクにラップして非同期メソッドとして使用することはお勧めできません。この方法では他のスレッドを使用し、より多くのリソースを使用するためです。これは、use async で回避したいことです。 .

この記事では TaskCompletionSource を使用していますが、正確な使用方法はわかりません。TaskCompletionSource の目的はどれですか?

4

2 に答える 2

4

asyncメソッドを記述するのに最適なリソースは、 Stephen Toub による Task-based Asynchronous Pattern (TAP) ドキュメントです。そのドキュメントの情報の多くは、公式の MSDN ドキュメントの一部になりました

短い (しかし完全な) チュートリアルが必要な場合は、私自身のasync/awaitイントロ ブログ投稿をお勧めします。他にもいくつかのチュートリアルがあります。について少し学んだらasync、次の良いリソースは公式async/ awaitFAQです。

asyncChannel9には素晴らしい動画がたくさんあります。彼らの多く (ほとんど?) はasync、CTP がまだ CTP だった頃について話し合っていますが、製品化されたときの設計変更はほとんどありませんでした。

特定の質問に答えるために、既存の非同期操作 (I/O 操作、タイマー、イベントなど) のラッパーTaskCompletionSourceを作成するために使用されます。created byTaskでコードを実行することはできません。でコードを実行するために使用する必要があります。TaskTaskCompletionSourceTask.RunTask

于 2012-12-11T14:57:19.817 に答える
2

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 より前に記述されたコードが、エラーなしでコンパイルされることが保証されます。Taskasync 修飾子は、 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することをお勧めします。これにより、同時実行の理解が深まります。

于 2012-12-11T11:06:45.717 に答える