DOBON.NETプログラミング道掲示板

No34695 の記事


■34695 / )  Re[1]: 非同期プログラミング時のConsole.WriteLineの動作
□投稿者/ Hongliang 大御所(599回)-(2021/04/11(Sun) 22:32:11)
  • アイコン
    確認ですが、
    ・アプリケーションのプロジェクトはWindows Formsアプリケーション
    ・デバッグ実行中
    ・Console.Write/WriteLineの出力はViual Studioの出力ウィンドウに出ている
    ということでいいでしょうか。
    
    > B 12行目をWriteLineからWriteに変えると、一切表示されなくなります。
    >     行終端記号の出力の有無が原因でしょうか?
    
    出力ウィンドウへの出力の場合、改行文字が現れない間は出力がバッファリングされます。
    
    > @ 1回目の実行で、08行めのConsoleWrite文が機能しません。なぜですか?
    
    機能はしています。
    ただ、前述のようにバッファリングされているので、まだ出力ウィンドウに表示されていない状態です。
    
    > A 2回目以後では、同じ数値が重複して表示されます。前回の残骸が表示されているように思いますが
    >  なぜですか? (キーバッファに残っているから?)
    
    1の続きになりますが、今回の実行でConsole.WriteLineによって改行文字が現れたため、
    前回までの実行でバッファリングされた状態の文字列が出力されています。
    (キー入力ではないのでキーバッファは関係ないです)
    
    > C MicroSoftのDocsによるとConsoleクラスは、スレッドセーフとなっていますが、
    >  08行目のWrite文が欠落する理由はなんでしょうか?
    
    先述の通り、欠落しているのではなく、後回しにされています。
    
    スレッドを起動するのはいくらかコストがかかるものです。
    なので、Task.Factory.StartNewを呼び出したからといって直ちにその中に書かれた処理が
    開始するわけではありません。
    さて、スレッドを起動中にも元々のスレッドの処理は継続します。
    > Dim continuation = Task.WhenAll(tasks)
    WhenAllメソッドは、「tasksの各処理が全部終わったら、完了状態となるTask」を用意しろという
    メソッドです。なので、WhenAll自体は特に何かを待つわけではありません。
    処理は継続します。
    > Console.WriteLine(" End")
    ここでEndが出力ウィンドウに渡されます。
    
    つまり、1回目のButton1_Clickでは、各Taskが起動しConsole.Writeが呼び出されるよりも先に、
    Console.WriteLineが呼び出されています。
    そのあとでConsole.Writeが順次実行されますが、先述通りこれはバッファリングされ、
    次回以降のButton1_ClickでConsole.WriteLineが行われるまでウィンドウには出てきません。
    
    1回目はEndが真っ先に出力されるのに2回目以降はいくつかその回のConsole.Writeが出力される点については、
    Task.Factory.StartNewが標準で使用するスレッドプールという仕組みに原因を求められますが、
    そこは一旦置いておいてもいいかと思います。
    
    List(Of Task)の全Taskの完了後に特定処理を実行したい場合、Task.WhenAllが返してきたTaskの完了後に
    その処理を実行する必要があります。
    以前はContinueWithを使って記述する必要がありましたが、最近は「Taskの完了後に処理をする」というのを
    手軽に書けるようになりました。
    
    Private Async Sub Button1_Click(略) 略
      ' 途中略
        Await Task.WhenAll(tasks)
        Console.WriteLine(" End")
    End Sub
    
    Asyncは「このメソッド内でAwaitキーワードを使うよ」という宣言です。
    AwaitはTaskに対して使用可能なキーワードで、
    「以降の処理を、Taskが完了した後で実行するように」という意味合いになります。

違反を報告
返信 削除キー/


Mode/  Pass/


- Child Tree -