web-dev-qa-db-ja.com

Async / AwaitはTask.Runを使用して新しいスレッドを非同期に開始していますか?

私は多くの記事を読みましたが、まだこの部分を理解できません。

このコードを検討してください:

    private async void button1_Click(object sender, EventArgs e)
    {
        await Dosomething();
    }

    private async Task<string> Dosomething()
    {
        await Task.Run((() => "Do Work"));
        return "I am done";
    }

最初の質問:

ボタンをクリックすると、DoSomethingが呼び出され、Task.Run(間違っていない場合)を呼び出してスレッドプールからスレッドを作成するタスクを待機し、すべてが非同期に実行されます。だから私は自分の仕事をするスレッドを作成することを達成しましたが、非同期でそれをしましたか?しかし、私は結果を返す必要はないことを考慮してください、私は結果を返さずに仕事をしたいだけです、本当にasync/awaitを使用する必要がありますか?

2番目の質問:

スレッドを非同期で実行する場合、どのように機能しますか?それはメインUIで実行されますが、別のスレッドで実行されますか、それとも別のスレッドで実行され、そのメソッドの内部で非同期に実行されますか?

33
syncis
  1. 非同期メソッドを作成する目的は、後で待機できるようにすることです。 「この水を沸騰させ、残りのスープの材料を準備し、鍋に戻って水が沸騰し終わるのを待って夕食を作ろう」というようなものです。あなたは他のことをしている間、それは非同期に行う水沸騰を開始しますが、最終的に停止し、それを待つ必要があります。あなたが望んでいるのが「燃えて忘れる」ことなら、AsyncとAwaitは必要ありません。

C#でfire and forgetメソッドを実行する最も簡単な方法

  1. 新しいタスクを開始すると、そのタスクはスレッドプールスレッドで実行するためにキューに入れられます。スレッドはプロセスのコンテキストで実行されます(アプリケーションを実行する実行可能ファイルなど)。これがIISで実行されているWebアプリケーションの場合、そのスレッドはIISワーカープロセスのコンテキストで作成されます。そのスレッドはメイン実行スレッドとは別に実行されるため、オフになり、メイン実行スレッドが何をしているかに関係なく、同時に、メイン実行スレッドは独自の作業を続けます。
18
DVK

タイプ Task<TResult> では、タスクからTResultを返す必要があります。返すものがない場合は、代わりに Task を使用できます(これは、ちなみにTask<TResult>の基本クラスです)。

ただし、タスクはスレッドではないことに注意してください。 タスクは実行されるジョブであり、スレッドはワーカーです。 プログラムが実行されると、ジョブとワーカーが使用可能および使用不可になります。背後では、ライブラリは利用可能なワーカーにジョブを割り当てます。新しいワーカーの作成はコストのかかる操作であるため、通常はスレッドプールを介して既存のワーカーを再利用することを好みます。

1

awaitTaskを使用しない場合、またはawaitを使用しない場合、大きな違いがあります。

  • ケースしないawait itDoSomethingが呼び出されますが、DoSomethingTaskは完了していません。

  • ケースyou await itDoSomethingが呼び出され、次の文が実行されますDoSomethingTask完了しました。

したがって、async/awaitの必要性は、DoSomethingの呼び出し方によって異なります。awaitを呼び出さない場合は、火を消して道を忘れる

2

それはメインUIで実行されますが、別のスレッドで実行されますか、それとも別のスレッドで実行され、そのメソッド内で非同期に実行されますか?

非同期コードは、他のスレッドを意味する場合があります(このQ&Aを参照してください 非同期とマルチスレッド-違いはありますか? )。つまり、コードがUIスレッドとは別のスレッドで実行されている場合、または再開中にUIスレッドの処理を続行できる場合、UIループは他のタスクが実行されている間に画面を更新できるため、 UIをフリーズせずに並列。

非同期メソッド(つまりasyncメソッド)は、awaitステートメントをステートマシンとして扱う必要があることをコンパイラーに伝えるための構文糖衣です。 C#コンパイラは、async/awaitコードをステートマシンに変換し、待機中のコードの後に​​Task結果を待機するコードが実行されるようにします。

興味深いQ&A

これらの他のQ&Aを確認することをお勧めします。

OPは言った...

[...]しかし、これは、「async/await」がスレッドを起動し、Task.Runもスレッドを起動することを意味しますか、それとも両方が同じスレッドですか?

async-awaitを使用することは、「スレッドを作成する」という意味ではありません。継続をエレガントな方法で実装するのは単なる構文上の砂糖です。タスクはスレッドであってもなくてもかまいません。たとえば、Task.FromResult(true)は、スレッドを作成する必要なしに非同期メソッドを実装できるように偽のタスクを作成します。

public Task<bool> SomeAsync()
{
    // This way, this method either decides if its code is asynchronous or 
    // synchronous, but the caller can await it anyway!
    return Task.FromResult(true);
}
9