Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

パターンでわかる! .NET Coreの非同期処理

1,005 views

Published on

セッションビデオ: https://www.youtube.com/watch?v=YF7n8YqEfCg
ブログ: https://www.kekyo.net/2019/10/07/6995

2019.10.5 .NET Conf 2019 meetup in AICHI
https://centerclr.connpass.com/event/143949/

Published in: Software
  • Be the first to comment

  • Be the first to like this

パターンでわかる! .NET Coreの非同期処理

  1. 1. www.dotnetconf.net
  2. 2. パターンでわかる! .NET Coreの 非同期処理 2019.10.5 .NET CONF 2019 MEETUP IN AICHI - KOUJI MATSUI (@KOZY_KEKYO, @KEKYO2)
  3. 3. Kouji Matsui – kozy, kekyo • NAGOYA city, AICHI pref., JP • Twitter – @kozy_kekyo, @kekyo2 / Facebook • Self employed (I’m looking for a job) • Microsoft Most Valuable Professional VS and DevTech 2015- • Certified Scrum master / Scrum product owner • Center CLR organizer. • .NET/C#/F#/IL/metaprogramming or like… • Bike rider
  4. 4. Agenda .NET Core 3とC# 8.0で完成した.NET非同期処理 .NET非同期処理のおさらい .NET非同期処理の現実と設計 追加された非同期処理の要素
  5. 5. What’s new features 本日は、以下のことをお話します: .NET非同期処理のおさらい ◦ 概要と基本的な書き方 ◦ コンソールアプリケーションとGUIアプリケーションとの違い ◦ お勧めしたいプラクティスとアンチパターン .NET非同期処理の現実と設計 ◦ 現実的なアプリケーションへの適用と課題 追加された非同期処理の要素 ◦ 足りなかったもの・足りていると勘違いされていたもの
  6. 6. What’s new features .NET Core 3とC# 8.0で、.NETの非同期処理はついに完成 Task async-await ValueTask IAsyncEnumerable Awaitable foreach 世 代
  7. 7. What’s new features .NET Core 3とC# 8.0で、.NETの非同期処理はついに完成 Task async-await ValueTask IAsyncEnumerable Awaitable foreach .NET Core 3 世 代
  8. 8. What’s new features .NET Core 3とC# 8.0で、.NETの非同期処理はついに完成 Task async-await ValueTask IAsyncEnumerable Awaitable foreach 非同期処理記述の 容易さの壁 (1) 非同期処理記述の 容易さの壁 (2) 世 代 今日は、壁より前の話や内部の話はしません。 なぜ非同期で処理を行う必要があるのかについては、 「Async訪ねて3000里」を参照
  9. 9. .NET非同期処理のおさらい 非同期処理、ポイントを押さえれば難しくありません。なの に、正しく書けてない、場合によっては危険なコードが散見さ れます。 .NET Core 3とC# 8.0で劇的に便利になったので、そろそろマス ターしちゃいましょう! 非同期処理を記述する際に遭遇する問題のパターンと、解決 の方策を示します。
  10. 10. 基本的な操作(1) – ファイルアクセス コンソールアプリケーションで非同期処理してみる ファイル出力を非同期処理で書いてみる
  11. 11. 基本的な操作(1) – ファイルアクセス 任意のデータを ファイルに出力する FileAccessWithAsync.csproj
  12. 12. 基本的な操作(1) – ファイルアクセス 注目すべきポイント
  13. 13. 基本的な操作(1) – ファイルアクセス I/O操作はすべて(Taskを返却する) 非同期対応メソッドを使用してawaitする
  14. 14. 基本的な操作(1) – ファイルアクセス メソッド中でawaitを使う場合は、メソッド 宣言でasyncとマークし、Taskを返す
  15. 15. 基本的な操作(1) – ファイルアクセス C# 7.1から、Mainメソッドが Taskを返せるようになった
  16. 16. 基本的な操作(1) – ファイルアクセス FileStreamクラス固有: falseまたは省略した場合は、 非同期I/Oはワーカースレッド によるシミュレート
  17. 17. ファイルアクセス Appendix ファイルアクセスでよく使われる Fileクラスのメソッド
  18. 18. ファイルアクセス Appendix Task.Runを使って、ワーカースレッドでシ ミュレートするのと同じなので、非効率
  19. 19. ファイルアクセス Appendix Mainメソッドの対処方法: C#7.0以前を使う場合は、このように非同期 メソッドにバイパスする (但しコンソールアプリケーションのみ)
  20. 20. 基本的な操作(2) – 独立した非同期処理 非同期処理を行うメソッドを作る 非同期処理を行うクラスライブラリを作る
  21. 21. 基本的な操作(2) – 独立した非同期処理 指定されたURLからJSON形式 のデータをダウンロードして パースするライブラリ IndependentLibrary.csproj
  22. 22. 基本的な操作(2) – 独立した非同期処理 注目すべきポイント
  23. 23. 基本的な操作(2) – 独立した非同期処理 メソッド中でawaitを使う場合は、メソッド 宣言でasyncとマークする
  24. 24. 基本的な操作(2) – 独立した非同期処理 メソッド内部で非同期処理を行い、結果 を値として返すので、Task<T>型とする
  25. 25. 基本的な操作(2) – 独立した非同期処理 Task<T>又はTaskを返す場合に、 メソッド名末尾にAsyncをつける (必須ではないが強く推奨) `async`とマークした場合、 ではないことに注意
  26. 26. 独立した非同期処理 Appendix 末尾にAsyncとつける推奨について: 1. 末尾にAsyncとついていれば、使用者が非同期処理対応の メソッドを容易に見分けられる(インテリセンスを活用 する意味でも重要) 2. よく見られる誤ったプラクティス: `async`とマークした場 合に、メソッド名末尾にAsyncと付ける… → TaskやTask<T>を返した場合に、末尾にAsyncを付ける Streamクラスのメンバー一覧
  27. 27. 独立した非同期処理 Appendix 抽象度の高いインターフェイス定義。 メソッドは値を返さない 誤ったプラクティスと考える理由 InterestingService.csproj
  28. 28. 独立した非同期処理 Appendix 共通のインターフェイスメソッドを 実装し、ログを出力する
  29. 29. 独立した非同期処理 Appendix ログ出力の負荷を軽減するため、バックグラ ウンドで出力するように改良。 呼び出し元はログがバックグラウンドで出力 されているかどうかを気にしなくても良い (=通知手段がないので出来ない)
  30. 30. 独立した非同期処理 Appendix ウェブサービスに アクセスする実装
  31. 31. 独立した非同期処理 Appendix メソッド中でawaitを使う場合は、メソッド 宣言でasyncとマークする
  32. 32. 独立した非同期処理 Appendix `async`とマークしているが、 末尾にAsyncと命名できない… `async`のマークは、内部でawaitキーワードを使っ たかどうかであって、非同期処理をするかどうか (インターフェイスの規定)とは関係がない
  33. 33. 独立した非同期処理 Appendix このメソッドは、同期的に値を返さない。 内部の処理は同期的に行われているかもしれないし、非同期的に行われて いるかもしれない(わからない)。 非同期的に行われているのであれば、その結果を知ることは出来ない。 このインターフェイスメソッドの 真の意味
  34. 34. WPFやWinFormsで非同期処理をおこなう 基本的な操作(3) – GUI内での操作
  35. 35. 基本的な操作(3) – GUI内での操作 ボタンが押されたら ファイルを生成する WPFアプリケーション WpfAppWithAsync.csproj
  36. 36. 基本的な操作(3) – GUI内での操作 注目すべきポイント
  37. 37. 基本的な操作(3) – GUI内での操作 メソッド中でawaitを使う場合は、メソッド 宣言でasyncとマークする
  38. 38. 基本的な操作(3) – GUI内での操作 イベントハンドラの戻り値をTaskにする ことは出来ない。その場合、voidだけが 非同期メソッドとして許される
  39. 39. 基本的な操作(3) – GUI内での操作 イベントハンドラの戻り値を Taskにすることは出来ない
  40. 40. 基本的な操作(3) – GUI内での操作 メソッド名末尾にAsyncと付けるプラクティスの背景と 同じことが、イベントハンドラについても言えます このメソッドは、同期的に値を返さない。 内部の処理は同期的に行われているかもしれないし、非同期的に行われて いるかもしれない(わからない)。 非同期的に行われているのであれば、その結果を知ることは出来ない。
  41. 41. 基本的な操作 Appendix 戻り値の型 直接的な意味 処理の詳細 Task<T> 非同期処理を行いT型の結果 を返す 非同期処理を行い、処理完了後に 結果を値として返す Task 非同期処理を行い結果を返さ ない 非同期処理を行い、処理完了後に 完了したことだけが通知される T 同期処理でT型の結果を返す、 又は結果を返しつつ非同期処 理の状態を返さない 通常の値を返すメソッド。しかし 場合によっては非同期処理が走っ ているかもしれない void 同期処理で結果を返さない、 又は非同期処理で状態も結果 も返さない 通常の値を返さないメソッド。し かし場合によっては非同期処理が 走っているかもしれない
  42. 42. .NET非同期処理の現実と設計 ここまでで、基本的な非同期処理の実装の方法を再確認して きました。 この節では、現実に発生しうる問題について、もう少し掘り 下げます。
  43. 43. 現実と設計(1) – 競合と回避 非同期処理中に競合条件が発生する場合、その回避方法を確 認します。 回避方法は非同期処理特有で、従来の手法が通用しないこと を知ってください。
  44. 44. 現実と設計(1) – 競合と回避 100回実行(つまり、100回インクリメント されるはず) RaceConditionWithAsync.csproj ファイル内の数値文字列を インクリメントして ファイルに書き戻す
  45. 45. 現実と設計(1) – 競合と回避 非同期処理 Task.WhenAllで、100個のTaskを 並列実行することになる
  46. 46. 現実と設計(1) – 競合と回避 100にならない… → 排他処理を何もしていないので、 競合が発生している
  47. 47. 現実と設計(1) – 競合と回避 awaitを使っていると、lockステートメントで モニターロックは出来ない (C#コンパイルエラー) モニターロック(ミューテックス)で 競合を回避したい、が…
  48. 48. 現実と設計(1) – 競合と回避 モニターロックを手動で構成…
  49. 49. 現実と設計(1) – 競合と回避 SynchronizationLockException: モニターロックが異なるスレッドで 解除されようとしている
  50. 50. 現実と設計(1) – 競合と回避 1 2 3 4 await await await 継続処理用ワーカースレッド群 (スレッドプールから取得) awaitの前後で、処理スレッドが変わる (かもしれない)
  51. 51. 現実と設計(1) – 競合と回避 1 2 3 4 await await await モニターロック取得スレッド モニターロック解放スレッド スレッドが一致していないので例外が発生
  52. 52. 現実と設計(1) – 競合と回避 つまりこの方法は根本的にダメ。 C#コンパイラが親切にlockを 使わせないようにしている
  53. 53. 現実と設計(1) – 競合と回避 NuGetパッケージ: Nito.AsyncEx Stephen Cleary氏の作品 ほぼlockステートメントと同じように使えて、 非同期処理対応(排他待機をawait出来る)
  54. 54. 現実と設計(1) – 競合と回避 .NET標準(ハードウェイト) Nito.AsyncEx(非同期処理対応) Monitor, lockステートメント AsyncLock, AsyncMonitor Mutex AsyncLock Semaphore AsyncSemaphore ManualResetEvent AsyncManualResetEvent AutoResetEvent AsyncAutoResetEvent ReaderWriterLock AsyncReaderWriterLock しかし、そもそも排他制御を行って いると、オーバーヘッドでパフォー マンスが上がらないと言う問題があ ります(重要) 他にもSlim版(SemaphoreSlimなど)がありますが、ハードウェ イトのみないし、部分的に非同期に対応しているのみなので、 非同期処理には推奨しません Nito.AsyncExを使うと、非同期処理 で安全に排他制御できます
  55. 55. 現実と設計(2) – GUIとスレッド GUIアプリケーションで非同期処理を行う場合は、コンソー ルアプリケーションとは異なる動きをします。 なぜ、GUIアプリケーションでは非同期処理が強く推奨され るのか、について掘り下げます。
  56. 56. 現実と設計(2) – GUIとスレッド ボタンが押されたら ファイル内の数値文字列を インクリメントする WPFアプリケーション WpfAppRaceConditionWithAsync.csproj
  57. 57. 現実と設計(2) – GUIとスレッド GUIアプリケーションでも 非同期処理は普通に使える
  58. 58. 現実と設計(2) – GUIとスレッド 1 2 3 4 await await await ①がメインスレッド その他はワーカースレッド (?) ワーカースレッドで実行され たら例外で死ぬのでは?
  59. 59. 現実と設計(2) – GUIとスレッド こう書くべき?? いいえ、Dispatcherを使ってメインスレッドに 明示的に転送しなくても問題ありません! なぜならば…
  60. 60. 現実と設計(2) – GUIとスレッド 1 await await await 実際にはメインスレッドしか 使われないからです!! メインスレッドで実行される
  61. 61. 現実と設計(2) – GUIとスレッド 1 await await await 根本的な疑問「なぜ非同期処理をGUIアプリケー ションに適用すると、ユーザーインターフェイス が固まらないのですか?」
  62. 62. 現実と設計(2) – GUIとスレッド 1 await await await awaitすると、メインスレッドは一時的にApplication.Run()の内部に戻ること が出来て、非同期処理が完了するまでは、別のイベントを処理できます (ボタンクリックイベント処理や、描画処理など) Application.Run() OnClick OnRender Application.Run() Application.Run()
  63. 63. 現実と設計(2) – GUIとスレッド 1 2 3 4 await await await await後の処理を 「継続処理」と呼びます 継続処理 (1) 継続処理 (2) 継続処理 (3) コンソールアプリケーションと どう違うのか?
  64. 64. 現実と設計(2) – GUIとスレッド 1 2 3 4 await await await デフォルトでは、継続処理の実行には、必ず ワーカースレッドが割り当てられます (メインスレッドとの区別はほとんどない) 継続処理 (1) 継続処理 (2) 継続処理 (3)
  65. 65. 現実と設計(2) – GUIとスレッド 継続処理 (1) 継続処理 (2) 継続処理 (3) 1 await await await WPFやWinFormsでは、継続処理の実行に、 常にメインスレッドが割り当てられます。 この制御を行っているのが、 SynchronizationContextの派生クラスです
  66. 66. 現実と設計(2) – GUIとスレッド いつもメインスレッドが継続処理を実行 しているとしたら、こうやって書いてい るのと同じようなものでは? (つまり、遅いのでは?) (厳密には違うのですが) パフォーマンスの懸念がある点では その通りです…
  67. 67. 現実と設計(2) – GUIとスレッド そこで、ConfigureAwait()を使います await await await 1
  68. 68. 現実と設計(2) – GUIとスレッド 1 2 3 4 await await await WPFデフォルトの挙動を無視し、以降は ワーカースレッドを割り当てるようになる もはや必ずワーカースレッドで実行されるので、 UIにアクセスする場合は、Dispatcherを使う必要があります
  69. 69. 現実と設計(2) – GUIとスレッド 1 2 3 4 await await await ワーカースレッド間の転送は比較的 低コストなので、この間の継続処理 は実行効率が高くなる ここはメインスレッドに 転送するコストが高い
  70. 70. 現実と設計(3) – 頻出パターン 非同期処理には、特有のパターンがあります。 うまくこのパターンに当てはめれば、高効率かつ劇的に簡単 に実装できるようになります。 競合と排他を避けるためにも、このパターンに乗せてくださ い。
  71. 71. 現実と設計(3) – 頻出パターン XMLデータをダウンロードして パースする 非同期パース対応(.NET Core 3から) AggregateThingsWithAsync.csproj
  72. 72. 現実と設計(3) – 頻出パターン 気象庁防災情報 XMLフォーマット形式電文 (中身はAtomフィード)
  73. 73. 現実と設計(3) – 頻出パターン Atomフィードのエントリn個を
  74. 74. 現実と設計(3) – 頻出パターン ダウンロードしてパースし、
  75. 75. 現実と設計(3) – 頻出パターン コメントを抽出する
  76. 76. 現実と設計(3) – 頻出パターン 2重ループ
  77. 77. 現実と設計(3) – 頻出パターン ループといえばLINQ
  78. 78. 現実と設計(3) – 頻出パターン 最初のAtomフィードの ダウンロードは同じ
  79. 79. 現実と設計(3) – 頻出パターン 内側のループに注目して、Task を返すメソッドやラムダ式に する
  80. 80. 現実と設計(3) – 頻出パターン 非同期ラムダブロック: Task<Xelement[]>
  81. 81. 現実と設計(3) – 頻出パターン XML LINQ
  82. 82. 現実と設計(3) – 頻出パターン Task.WhenAllで、複数のTaskを一度に 非同期待機する
  83. 83. 現実と設計(3) – 頻出パターン 並列実行され、 やがて結果がまとめて返される
  84. 84. 現実と設計(3) – 頻出パターン 結果を全て出力
  85. 85. 現実と設計(3) – 頻出パターン entry Text Text Text entry Text Text entry Text Text Text Text entry Text WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine 動きを振り返ってみます
  86. 86. 現実と設計(3) – 頻出パターン entry Text Text Text entry Text Text entry Text Text Text Text entry Text foreachの2重ループ 逐次実行 WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine ChattyなUIへのアクセス (GUIの場合、ボトルネックになりうる)
  87. 87. 現実と設計(3) – 頻出パターン entry Text Text Text entry Text Text entry Text Text Text Text entry Text WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine entry Text Text Text entry Text Text entry Text Text Text Text entry Text TextTextText TextText TextTextText Text Text TextTextTextTextTextTextText WriteLine
  88. 88. 現実と設計(3) – 頻出パターン entry Text Text Text entry Text Text entry Text Text Text Text entry Text WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine WriteLine entry Text Text Text entry Text Text entry Text Text Text Text entry Text TextTextText TextText TextTextText Text Text TextTextTextTextTextTextText WriteLine LINQでそれぞれの Textを集約 Task.WhenAllで 全部の非同期 を集約Task Task Task Task
  89. 89. 現実と設計(3) – 頻出パターン entry Text Text Text entry Text Text entry Text Text Text Text entry Text TextTextText TextText TextTextText Text Text TextTextTextTextTextTextText WriteLine Task Task Task Task 内側の処理をそれぞれ独立させて、 相互に依存しないようにします 並列実行性が高まります(安全) →モデル設計 M-(V-VM)
  90. 90. 現実と設計(3) – 頻出パターン entry Text Text Text entry Text Text entry Text Text Text Text entry Text TextTextText TextText TextTextText Text Text TextTextTextTextTextTextText WriteLine 全部の非同期処理を集約 するだけ 全部集約されてから、UIにアクセス 裏を返すと全部集約されないと UIにアクセスできない (トレードオフ)
  91. 91. 現実と設計 Appendix 補足
  92. 92. 現実と設計 Appendix ハードウェイト(ハードブロック) ◦ スレッドを(WindowsやLinuxなどのOSカーネルの機能で)一時停止させること。非同 期処理に対して、非互換。例外やデッドロックを引き起こす可能性があります。 ◦ Thread.Sleep(), Thread.Join() ◦ Monitor.Enter() ◦ WaitHandle.WaitOne(), WaitHandle.WaitAny(), WaitHandle.WaitAll() ◦ Task.Wait(), Task.Result いつも言っていますが、ここまでの解説で、 上記は一切使っていません。 「Task.Wait(), Task.Resultは使いません・使えません・ 使う必要がありません!!」
  93. 93. 現実と設計 Appendix 非同期処理(待機可能・Awaitable) ◦ 実行単位をスレッドではなく、抽象的なタスクとみなし、タスクを一 時停止させる。タスクを実行するのはスレッドですが、特定のタスク がいつも特定のスレッドで実行されるとは限りません。 ◦ Task.Delay() ◦ Stream.ReadAsync(), Stream.WriteAsync() ◦ TextReader.ReadLineAsync(), TextWriter.WriteLineAsync() ◦ HttpClient.GetAsync(), HttpClient.PostAsync() 上記は全てTask又はTask<T>を返します。
  94. 94. 現実と設計 Appendix ハードウェイトを行うメソッドを非同期処理と混ぜて安全に (かつパフォーマンスを最大化して)使用するのは、トップレ ベルの技術者でも非常に困難です(あるいは不可能)。 つまり、やりたくなったら 何かが間違っています いやでも今自分が遭遇している問題は、当てはまらない レアケースだから… と言っている問題も間違いです
  95. 95. 追加された非同期処理の要素 ValueTaskはTaskのメモリ確保コストを削減します。 非同期イテレーターインターフェイスが、標準定義され、非 同期イテレーターを列挙する構文・列挙可能にする構文が、 C#8.0で追加されました。 非同期イテレーターを活用すれば、モデル実装がより簡単に なります。
  96. 96. 追加された非同期処理の要素(1) – ValueTask ValueTaskをTaskの代わりに使っていきたい動機について。 なぜ効率が良いのか?
  97. 97. 追加された要素(1) – ValueTask ValueTaskはTaskの構造体版
  98. 98. 追加された要素(1) – ValueTask AggregateThingsWithAsync.csproj
  99. 99. 追加された要素(1) – ValueTask 1. Taskで宣言していたところを機械的にValueTaskに置 き換え出来る。 2. Taskで出来ることはValueTaskでもだいたいできる。 3. ValueTask.AsTask()を呼び出せばTaskに変換できる。 ValueTask.WhenAllはないが、Taskを 返す非同期処理を混ぜて使える
  100. 100. 何が嬉しいの? ◦ もし、非同期処理がその場で完了した場合(たとえば、ReadLineAsync() の読み取りがバッファリングされていたデータなどで直ぐに返せるな ど)、TaskだとTaskクラスのインスタンス生成にコストが掛かるけど、 ValueTaskならほとんどコストがかからない(構造体だから) ◦ 非同期待機が実際に発生する場合に、初めて内部でTaskのインスタンス が生成される。 追加された要素(1) – ValueTask
  101. 101. つまり? async-await構文でawaitしまくるコードを書いた場合: ◦ Taskだとawaitの度にTaskのインスタンスが生成されるので、効率が悪い ◦ ValueTaskだと結果が直ぐに得られる場合は、インスタンス生成コスト が発生しない 追加された要素(1) – ValueTask 注意: ValueTaskを使う場合は、 System.Threading.Tasks.Extensions パッケージを追加する必要があります
  102. 102. 追加された要素(2) – 非同期イテレーター Task.WhenAllが配列を返す件。 yield returnを非同期処理と組み合わせて使えます。
  103. 103. 追加された要素(2) – 非同期イテレーター データ群の処理方法 foreachによる逐次処理 Task.WhenAllによる集約処理 メリット 従来のループ手法をそのまま適用 できる。 出力やUIへの反映が逐次実行され る(インタラクティブ性・スト リーミング) 集合演算に根付く考え方に適合する なら、非常に直感的で高レベルな記 述が可能(LINQ)。 モデル設計として独立させやすい。 並列実行される。 デメリット 並列処理がやりにくい、あるいは そのままでは出来ない。 モデル設計として処理を完全に分 離することが難しい。 全てのデータが集約されてからしか、 結果にアクセスできない(配列)。
  104. 104. 追加された要素(2) – 非同期イテレーター entry Text Text Text entry Text Text entry Text Text Text Text entry Text TextTextText TextText TextTextText Text Text WriteLine TextTextTextTextTextTextText
  105. 105. 追加された要素(2) – 非同期イテレーター entry Text Text Text entry Text Text entry Text Text Text Text entry Text TextTextText TextText TextTextText Text Text Text Text Text Text Text WriteLine この部分を、データが得られたところ から逐次実行できないものか…
  106. 106. AggregateThingsWithAsync.csproj 追加された要素(2) – 非同期イテレーター
  107. 107. 追加された要素(2) – 非同期イテレーター IAsyncEnumerable<T>で、列挙可能で かつ非同期処理を実現できる
  108. 108. 追加された要素(2) – 非同期イテレーター 普通にawaitできる
  109. 109. 追加された要素(2) – 非同期イテレーター IEnumerable<T>と同じように、 yield returnで要素を返せる
  110. 110. 追加された要素(2) – 非同期イテレーター 実装の詳細が外部に漏れていない、 真に独立したモデルメソッドを実現
  111. 111. 追加された要素(2) – 非同期イテレーター 非同期イテレーターは、 新しいawait foreachという構文で、 非同期的に列挙できる
  112. 112. 追加された要素(2) – 非同期イテレーター awaitを付けたからasyncを忘れずに
  113. 113. 追加された要素(2) – 非同期イテレーター 非同期イテレーターとは? ValueTaskを使う。 つまり、連続してすぐに値を返せる場合は、 Taskよりもコストが低い
  114. 114. 追加された要素(2) – 非同期イテレーター foreachによる逐次処理 Task.WhenAllによる集約処理 非同期イテレータを使う処理 メリット 従来のループ手法をそのま ま適用できる。 出力やUIへの反映が逐次実 行される(インタラクティ ブ性・ストリーミング) 集合演算に根付く考え方に適 合するなら、非常に直感的で 高レベルな記述が可能 (LINQ)。 モデル設計として独立させや すい。 並列実行される。 従来のループ手法をそのまま適 用できる。 出力やUIへの反映が逐次実行さ れる(インタラクティブ性・ス トリーミング) モデル設計として独立させやす い。 デメリット 並列処理がやりにくい、あ るいはそのままでは出来な い。 モデル設計として処理を完 全に分離することが難しい。 全てのデータが集約されてか らしか、結果にアクセスでき ない(配列)。 並列処理がやりにくい、あるい はそのままでは出来ない。
  115. 115. Any question? Thank you for join!! スライドのコードは全てここにあります: https://github.com/kekyo/dotnetconf2019
  116. 116. Any question? Thank you for join!! https://github.com/kekyo/dotnetconf2019

×