web-dev-qa-db-ja.com

Task.Runを非同期にするためのメソッドに入れる必要がありますか?

私は非同期を最も単純な形で理解しようとしています。この例のために2つの数値を追加する非常に単純な方法を作成したいのですが、当然のことながら、まったく処理時間はありません。ここで例を作成するだけの問題です。

例1

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

例2

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

DoWork1Async()を待つと、コードは同期的または非同期的に実行されますか?

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

私のメソッドがTaskであるかTask<T>を返すのかを把握しようとしていますか。非同期にするには、コードをTask.Runでラップする必要があります。

愚かな質問私は確信していますが、Task.RunStartNewにラップされていない、非同期なコードをユーザーが待っているという例がネット上にあります。

270
Neal

メソッドをasyncで装飾するときに覚えておくべき最も重要なことの1つは、少なくともメソッド内にoneawait演算子があることです。 。あなたの例では、 TaskCompletionSource を使って以下のように翻訳します。

private Task<int> DoWorkAsync()
{
    //create a task completion source
    //the type of the result value must be the same
    //as the type in the returning Task
    TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
    Task.Run(() =>
    {
        int result = 1 + 2;
        //set the result to TaskCompletionSource
        tcs.SetResult(result);
    });
    //return the Task
    return tcs.Task;
}

private async void DoWork()
{
    int result = await DoWorkAsync();
}
21
Ronald Ramos

Task.Runを使用してメソッドを実行すると、Taskはそのメソッドを実行するためにthreadpoolからスレッドを取得します。そのため、UIスレッドの観点からは、UIスレッドをブロックしないので「非同期」です。デスクトップアプリケーションにとっては、通常はユーザー操作の面倒を見るのに多くのスレッドを必要としないため、問題ありません。

ただし、Webアプリケーションの場合、各要求はスレッドプールスレッドによって処理されるため、アクティブスレッドの数はスレッドを節約することによって増やすことができます。非同期操作をシミュレートするためにスレッドプールスレッドを頻繁に使用することは、Webアプリケーションには拡張できません。

True Asyncは必ずしもファイル/ DBアクセスなどのI/O操作にスレッドを使用する必要はありません。これを読んで、I/O操作がスレッドを必要としない理由を理解できます。 http://blog.stephencleary.com/2013/11/there-is-no-thread.html

あなたの簡単な例では、それは純粋なCPU縛られた計算である、それでTask.Runを使うことは問題ない。

11
zheng yu