10

私はasync/awaitキーワードについて読んでいて、それを読みました:

ロジックの流れが await トークンに到達すると、呼び出しスレッドは呼び出しが完了するまで中断されます。

さて、私は単純な を作成しwindows forms application、ボタンとテキストボックスの 2 つのラベルを配置し、コードを書きました。

        private async void button1_Click(object sender, EventArgs e)
        {
            label1.Text = Thread.CurrentThread.ThreadState.ToString();
            button1.Text =  await DoWork();
            label2.Text = Thread.CurrentThread.ThreadState.ToString();
        }

        private Task<string> DoWork()
        {
            return Task.Run(() => {
                Thread.Sleep(10000);
                return "done with work";
            });            
        }

私が理解していないのは、ボタンをクリックすると、label1 にテキストがRunning表示され、10 秒後にのみ label1 に同じテキストが表示されるということですが、この 10 秒でテキストボックスにテキストを入力できたので、メインスレッドが実行されているようです...

では、async/await はどのように機能するのでしょうか?

ここに本の「スクリーンショット」があります: ここに画像の説明を入力

よろしく

4

4 に答える 4

22

私はそれを読んだ:ロジックのフローが待機トークンに達すると、呼び出しが完了するまで呼び出し元のスレッドが中断されます。

そのナンセンスをどこで読みましたか?引用していない文脈があるか、それが含まれているテキストを読むのをやめるべきです。await のポイントは、そのを行うことです。await のポイントは、非同期タスクが実行中の間、現在のスレッドが有用な作業を実行し続けることです

更新: あなたが参照した本をダウンロードしました。そのセクションの絶対にすべてが間違っています。この本は捨てて、もっと良い本を買いましょう。

私が理解していないのは、ボタンをクリックすると、label1 に Running というテキストが表示され、10 秒後にのみラベルに同じテキストが表示されるということですが、この 10 秒でテキストボックスにテキストを入力できました。メインスレッドが実行されているようです...

そのとおりです。何が起こるかは次のとおりです。

        label1.Text = Thread.CurrentThread.ThreadState.ToString();

テキストが設定されます。

        button1.Text =  await DoWork();

ここでいろいろなことが起こります。最初に何が起こりますか? DoWorkと呼ばれます。それは何をするためのものか?

        return Task.Run(() => { Thread.Sleep(10000);

スレッドプールからスレッドを取得し、そのスレッドを 10 秒間スリープさせ、そのスレッドによって実行されている「作業」を表すタスクを返します。

ここに戻ってきました。

        button1.Text =  await DoWork();

私たちには仕事があります。Await は、最初にタスクをチェックして、タスクが既に完了しているかどうかを確認します。そうではない。次に、このメソッドの残りをタスクの継続として登録します。その後、呼び出し元に戻ります。

ねえ、その呼び出し元は何ですか? とにかく、どうやってここに来たのですか?

一部のコードは、このイベント ハンドラーを呼び出しました。Windows メッセージを処理しているのはイベント ループでした。ボタンがクリックされ、返されたばかりのクリック ハンドラーにディスパッチされたことを確認しました。

さてどうなる?イベント ループが実行され続けます。お気づきのように、UI は問題なく動作し続けます。最終的に、そのスレッドは 10 秒刻みになり、タスクの継続がアクティブになります。それは何をしますか?

これにより、「イベント ハンドラの残りを今すぐ実行する必要があります。探していた結果が得られました」というメッセージが Windows キューにポストされます。

メイン スレッドのイベント ループは、最終的にそのメッセージに到達します。したがって、イベント ハンドラーは中断したところから再開します。

        button1.Text =  await DoWork();

await はタスクから結果を抽出し、それをボタン テキストに格納して、イベント ループに戻ります。

于 2016-06-06T22:56:53.683 に答える
0

を書くことawaitで、あなたは言っている - この時点でメソッドの実行を停止し、DoWork終了するのを待ってから続行してください。

「非同期メソッドで何が起こるか」セクションのasync と await を使用した非同期プログラミング (C#)には、メソッドで何が起こるかについて、図を使用して段階的に説明されていasyncます。

さらに良い説明がawait (C# リファレンス)にあります。WaitSynchronouslyおよび以下のコメントをWaitAsynchronouslyAsyncご覧ください。

記事には次のようにも記載されています(強調は私のものです):

await 演算子は、非同期メソッドのタスクに適用され、待機中のタスクが完了するまでメソッドの実行を中断します。タスクは進行中の作業を表します。

private async void button1_Click(object sender, EventArgs e)
{
    // Call the method that runs asynchronously.
    string result = await WaitAsynchronouslyAsync();

    // Call the method that runs synchronously.
    //string result = await WaitSynchronously ();

    // Display the result.
    textBox1.Text += result;
}

// The following method runs asynchronously. The UI thread is not
// blocked during the delay. You can move or resize the Form1 window 
// while Task.Delay is running.
public async Task<string> WaitAsynchronouslyAsync()
{
    await Task.Delay(10000);
    return "Finished";
}

// The following method runs synchronously, despite the use of async.
// You cannot move or resize the Form1 window while Thread.Sleep
// is running because the UI thread is blocked.
public async Task<string> WaitSynchronously()
{
    // Add a using directive for System.Threading.
    Thread.Sleep(10000);
    return "Finished";
}
于 2016-06-06T22:33:20.317 に答える