async/await
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
「[[マイクロソフト系技術情報 Wiki>http://techinfoofmicros...
-[[戻る>非同期処理]]
* 目次 [#l24f314e]
#contents
*概要 [#d9ab14bf]
**はじめに [#rb3ca86b]
-async/awaitの登場で、マルチスレッド処理として実装しなく...
非同期処理を同期型処理と、ほぼ変わらない記述で容易に実装...
-awaitの意味は、
--スレッドを止めずノンブロッキングで
--非同期から同期に復帰する
>という意味らしい。
-実際、async/awaitはそういう動きをする。~
--スレッドやWindowsメッセージングキューでTask化される。~
昔懐かしい、[[ノンプリエンプティブ・マルチタスク]](Win3.1...
--しかし、その実態はとても複雑(詳しくは[[コチラ>#nc34461...
---内部がどう動いているか詳しく把握しないとシステムは安定...
---中身をシッカリ理解して使用している人が少ないので注意が...
**用途 [#kb0ddc1e]
主に、非同期処理(≠並列処理)を簡単に(同期処理的に)実装...
-UIスレッドからのサーバ呼出のハングアップを防止するために...
-または、内部的には、UIスレッドから、時間のかかるバックグ...
(ネットワーク バインドまたは I/O バインドの処理)を分離...
-Webサーバのスレッド枯渇を防ぐ[[非同期Controller>ASP.NET ...
-並列実行処理を実装するための基盤ではない。
--[[Fire & Forget>#hc2dffee]]やTask.WhenAllで並列実行処理...
await、Task.Wait()の"待ち合わせ"までがセットになっている...
そもそも、並列実行処理を実装することに特化した基盤ではな...
(非同期タスクを作成して待つ処理を同期的に書ける仕組みと...
--並列実行処理を実装する場合は、Threadや、ThreadPoolを使...
**使い方 [#l81605a4]
async/awaitの登場で、非同期処理を同期型処理と、ほぼ変わら...
-asyncで修飾したTaskを返す非同期メソッドから、awaitステー...
-若しくは、Task.Run()で実行して、Task.Wait()で待ち合わせ...
しかし、デバッグの時は非同期で実行されていることを意識す...
(しかも、かなり特殊な。同期コンテキスト毎に動作も大きく...
**仕組み [#kaa7ba64]
-非同期化からのノンブロッキングの復帰には同期コンテキスト...
-同期コンテキストにはWindowsメッセージングキュー、ThreadP...
-仕組みの詳細については[[コチラ>#nc344611]]を参照。
async/await]]は、TAP(Task-based Asynchronous Pattern)の...
async/awaitは、
-メッセージ(番号)のような制約のある単純固定長値のキューで...
実行コードの任意のコード断片そのものをキュー(同期コンテ...
-.NET 3.5用のasync/await互換NuGetパッケージでは、~
.NET 4のTask互換クラスを、内部をBeginInvoke等で実装して、...
**余談 [#ef267401]
async/awaitの夫々の意味。
-async修飾子~
asyncは、呼び出し元と同じ同期コンテキストで実行されること...
-await演算子~
asyncをawaitすると、スレッドを止めずに同期コンテキストで...
この動作は想像し難いが、具体的には、
-同じ同期コンテキスト(Windowsメッセージングキュー)に
-コールバックを順番に並べる(Control.BeginInvoke()的な)。
というイメージ。
-・・・結局、APM、EAPと同じ技術(同期コンテキスト)を使っ...
-なお、同期コンテキストの種類によって、動きも異なる。
--同期コンテキストはキュー的なもので実装されている。~
例えば、前述の、
---Windowsメッセージングキュー、
---ThreadPool
---I/O 完了ポート
---, etc.
--なので、言葉尻だけで動作を想像し難く、~
[[利用の際は注意が必要になってくる>#c3aa7761]]。
*実装方法 [#je886ba3]
**タスク分割方法 [#gb4b4431]
await(Task.Run)を切れ目として、~
プログラマが意識して時間のかかるバックグラウンド処理~
(ネットワーク バインドまたは I/O バインドの処理)を分割...
***await [#d6f183d7]
-await前の処理はフォアグラウンド的に実行される。
-awaitで呼び出す非同期メソッドはバックグラウンド的に実行...
-await後の処理は、コールバックとして実装せずにフォアグラ...
--厳密に言うとフォアグラウンドに復帰ではなく、~
プログラムのコード上、非同期処理の後続処理に復帰する。~
--例えば、[[非同期Controller>ASP.NET MVCの用語#lc319892]]...
---非同期スレッド側で実行され、最後にリクエストを受け付け...
---この動作は、システム的には、フォアグラウンドに復帰する...
***Task.Run ~ Task.Wait() [#t097d303]
-Task.Run前の処理はフォアグラウンド的に実行される。
-Task.Run()で呼び出す非同期メソッドはバックグラウンド的に...
-Task.Wait()後の処理は、コールバックとして実装せずして、...
-Task.Waitが呼ばれるとスレッドはTaskが終わるまで待機する。
-これらの動きの詳細は、同期コンテキストによって異なってく...
-また、Task.Waitを使用すると、同期コンテキスト上、~
実行する非同期Taskの前に、Task.Waitが割り込むとデッドロッ...
**非同期メソッドの戻り値 [#b43ff41c]
***void型 [#w5cf9ec2]
[[Fire & Forget>#hc2dffee]]の場合、戻り値は不要。
***Task型 [#t98c2e31]
[[Awaitable>#v7df61f1]]の場合、
-戻り値の無い非同期メソッドを実装する場合、Task型の戻り値...
-基本的に、returnを書く必要はない。
-しかし、非同期メソッド内で非同期処理を呼び出さない場合、~
[[Task.FromResult>#vfa22973]]で、完了状態のTaskを生成する...
await Task.FromResult(0);
await Task.FromResult(default(object));
***Task<T>型 [#td2f6464]
[[Awaitable>#v7df61f1]]の場合、
-T型の戻り値の有る非同期メソッドを実装する場合、Task<T>型...
-戻り値はTask<T>型だが、awaitした後、Tの型の値をreturnす...
int ret = await XXXXAsync();
return ret;
-しかし、非同期メソッド内で非同期処理を呼び出さない場合、~
[[Task.FromResult>#vfa22973]]で、完了状態のTask<T>を生成...
await Task.FromResult(new T());
***Task.FromResult [#vfa22973]
Task.FromResultを使用すると、完了状態のTaskを生成すること...
-以下のようなケースで利用する。
--戻り値のTaskが長いコード パスを実行することなく、直ぐ完...
--インターフェイス上はTaskを返すが、メソッド内で非同期処...
-詳細については、下記を参照のこと。
--Task.FromResult(TResult) メソッド (TResult) (System.Thr...
https://msdn.microsoft.com/ja-jp/library/hh194922.aspx
--c# - If my interface must return Task what is the best ...
https://stackoverflow.com/questions/13127177/if-my-interf...
**非同期メソッドの呼び出し [#s278988c]
***await演算子 [#z7b2e8a4]
-Task の実行が完了したら、待機せずに、~
フォアグラウンドに復帰する風な動きを見せる。
--await 非同期メソッド()
--await Task.Run()
-await演算子の使い方
--非同期メソッドを呼び出すときに、await演算子を利用する。
--メソッド内でawait演算子を利用する場合、async修飾子でメ...
--await演算子は、async修飾子の付くメソッドの中で1つ以上...
***Task.Run()・Task.Wait()、Task.WhenAll()メソッド [#l8b4...
-Task.Run()メソッド
--非同期メソッドを実行してTask、Task<TResult>を返す。
-Task.Wait()
--Task、Task<TResult>の実行が完了するまで待機する。
--async/awaitと異なり、同期コンテキストで同期せず、~
待機(ブロック)した後にフォアグラウンドに復帰する。
-Task.WhenAll()
--メソッドで複数のタスクを待機するタスクを取得する。
--このTaskをTask.Wait()するとTask毎の~
例外をAggregateException型として取得可能。
**非同期メソッドの作り方 [#rc951c69]
***参考 [#uc071d5f]
- [.NET Framework 4/4.5][C# 5] 非同期で動くビジネスロジッ...
: biac の それさえもおそらくは幸せな日々@nifty~
http://bluewatersoft.cocolog-nifty.com/blog/2011/12/net-f...
-Task.Start()、Task.Factory.StartNew()、Task.Run()
--Task クラスと TaskFactory クラス~
http://www.kanazawa-net.ne.jp/~pmansato/parallel/parallel...
--Task.Start()とTask.Run()とTask.Factory.StartNew()の違い...
http://fromfulltofree.blog.fc2.com/blog-entry-7.html
- [雑記] スレッド プールとタスク~
C# によるプログラミング入門 | ++C++; // 未確認飛行 C~
http://ufcpp.net/study/csharp/misc_task.html
-Provide an asynchronous version method for call the B-la...
from the action method of asynchronous controller.~
· Issue #216 · OpenTouryoProject/OpenTouryo~
https://github.com/OpenTouryoProject/OpenTouryo/issues/216
*詳細 [#nc344611]
ここでは、
-「非同期メソッドの種類」と
-「同期コンテキスト」の
組み合わせによって、await後の処理が、~
どのように実行されるのかについて説明する。
-参考
--async/awaitと同時実行制御 | ++C++; // 未確認飛行 C ブロ...
https://ufcpp.wordpress.com/2012/11/12/asyncawait%E3%81%A...
---An other world awaits you~
http://www.slideshare.net/ufcpp/an-other-world-awaits-you
**非同期メソッドの種類 [#yc35ca64]
非同期メソッドには、2種類ある。
-[[Fire & Forget>#hc2dffee]]~
戻り値がvoidのメソッド
-[[Awaitable>#v7df61f1]]~
戻り値がTask(もしくはTask<T>)のメソッド
***Fire & Forget [#hc2dffee]
非同期メソッドでもreturn文を書く必要が無い。
戻り値がvoidなので非同期以降がフォアグラウンドに復帰しな...
-非同期呼び出しで投げっぱなす場合。
-具体的には、GUIアプリケーションのイベント・ハンドラに適...
-上記以外の用途での利用は意味もなく、ハマる原因になるので...
***Awaitable [#v7df61f1]
非同期メソッドは、Task、Task<T>をリターンする。
戻り値がTask(もしくはTask<T>)なので、await演算子かWait(...
以降に実装された非同期以降がフォアグラウンドに復帰する。
-非同期呼び出しの呼び出し元で
--awaitで、非同期以降をフォアグラウンドに復帰させる場合。
--Task.Wait()で呼び出し元が非同期メソッドの完了を待機する...
**同期コンテキスト [#je52c46b]
実行環境によって持つ同期コンテキストの種類が異なる。
***GUIアプリケーション [#yc5c5030]
GUIアプリケーションでの同期コンテキストは~
「Windowsメッセージングキュー(Control.Invoke、.BeginInvo...
-Fire & Forget~
GUIアプリケーションのawaitの次の処理は、~
同期コンテキストのControl.BeginInvokeによって、~
UIスレッド上でシーケンシャルに実行される。
-Awaitable~
該当なし?Control.Invokeでは?
***Consoleアプリケーション [#ibd79536]
Consoleアプリケーションでの同期コンテキストは「null」にな...
-Fire & Forget~
非推奨(Threadや、ThreadPoolを使用すればイイ)
-Awaitable
--Consoleアプリケーション内のawaitの次の処理が実行される...
--ただし、処理自体は、(記述した順に)シーケンシャルに実...
***ThreadPool [#cf19c6b3]
Task.Runを使用した場合の同期コンテキストは、~
マルチスレッド環境下の「ThreadPool」になる。
-Fire & Forget~
非推奨(Threadや、ThreadPoolを使用すればイイ)
-Awaitable
--Task.Run内のawaitの次の処理が実行されるスレッドは一意で...
--且つ、Task.Run内のawaitの次の処理は、UIスレッドに戻らな...
--ただし、処理自体は、(記述した順に)シーケンシャルに実...
***ASP.NET [#s4df3070]
ASP.NETアプリケーションでの同期コンテキストは~
マルチスレッド環境下の「System.Threading.SynchronizationC...
-Fire & Forget~
非推奨(Threadや、ThreadPoolを使用すればイイ)
-Awaitable
--ASP.NETアプリケーションのawaitの次の処理が実行されるス...
--ただし、処理自体は、(記述した順に)シーケンシャルに実...
--HttpContext等の保持、非同期処理が全て終わるまで、レスポ...
--最終的に結果は、リクエストを受け付けたスレッドにバイン...
詳しくは、[[非同期Controller>ASP.NET MVCの用語#lc319892]]...
この辺の
-asp.net mvc - MVC Action Filters Collection was modified;~
enumeration operation may not execute - Stack Overflow~
http://stackoverflow.com/questions/29429526/mvc-action-fi...
スタック・トレースを見ると、
-「SynchronizationContext」と
-「AsyncControllerActioninvoker」は
同じ事らしいと解る。
なお、恐らく、これらの同期コンテキストは、~
I/O完了ポート(IOCP)= ノンブロッキングI/Oであると思われ...
-Can ASP.NET MVC's AsyncController be used to service lar...
concurrent hanging requests (long poll)? - Stack Overflow~
http://stackoverflow.com/questions/4982882/can-asp-net-mv...
***並列実行 [#k847f44a]
-GUI以外の同期コンテキストでFire & Forgetを実行した場合(...
-Task.WhenAllで複数のTaskをTask.Wait()した場合(ThreadPoo...
並列実行を始めるので、~
特に、Consoleアプリケーションの同期コンテキスト(null)の...
新規に[[同期処理>#z135f913]]の実装が必要になることがある。
*同期 [#w87411f4]
async/awaitは非同期呼び出しで投げっぱなした後に、~
同期コンテキストにより同期される方式のため、同期をあまり...
同期コンテキストによっては、同期を行う必要があるため、以...
**仕組みから [#ab98fed9]
スレッドを使用した処理を記述しないが、
分割されたタスクは、
-同一スレッドで動作することも
-別スレッドで動作することもある。
このため、一連の処理が(分割されたタスクが)、
-異なるスレッドで実装される保証は無い。
-同じスレッドで実行される保証も無い。
**スレッド同期ツールキットは使用不可 [#sdd9c0ad]
従って、スレッド同期のlock等は無意味。~
従来のスレッド同期ツールキットは使用不可。
***lock/mutex/semaphoreはtaskで全て使用禁止 [#offf1b54]
旧プログラムで、
+スレッド・アフィニティのあるロック機構(lock/mutex/semap...
+awaitを使用して修正変更をしたい場合(await演算子を含むコ...
スレッド・アフィニティのないロック機構を使用する。
***WaitFor[Single|Multi]Objectは例外的に使用可 [#z135f913]
Win32の待機関数のWaitFor[Single|Multi]Objectは例外的に使...
これらの待機関数は、
-スレッド・アフィニティではなく、
-「状態変化」(ノンシグナル状態からシグナル状態への変化)を
待つ関数であるためと考える。
-スレッド・アフィニティのないロック機構
--.NET TIPS:非同期:awaitを含むコードをロックするには?...
http://www.atmarkit.co.jp/ait/spv/1411/11/news117.html
---SemaphoreSlim.WaitAsync関数もasync/awaitする。
---Semaphoreによるlockさえ、タスクとして分割されて待機/実...
--ThreadPool クラス (System.Threading)~
https://msdn.microsoft.com/ja-jp/library/system.threading...
---ThreadPool.RegisterWaitForSingleObject メソッド (Syste...
https://msdn.microsoft.com/ja-jp/library/system.threading...
--EventWaitHandle クラス (System.Threading)~
https://msdn.microsoft.com/ja-jp/library/system.threading...
---AutoResetEvent クラス (System.Threading)~
https://msdn.microsoft.com/ja-jp/library/system.threading...
---ManualResetEvent クラス (System.Threading)~
https://msdn.microsoft.com/ja-jp/library/system.threading...
*その他 [#r19de18d]
**進捗報告 [#p80858da]
上記の仕組みで動いているとすると、進捗報告をどう実装する...
以下を見ると、Progressクラス、IProgress<T>インターフェー...
-非同期メソッド - C# によるプログラミング入門 | ++C++; //...
http://ufcpp.net/study/csharp/sp5_async.html#cancel
-.NET TIPS:WPF/Windowsフォーム:~
時間のかかる処理をバックグラウンドで実行するには?(async...
http://www.atmarkit.co.jp/ait/articles/1512/02/news019.html
詳しい仕組みは不明だが、GUI上で動作しているため、~
同期コンテキストのControl.Invoke、.BeginInvokeを使用して...
**CancellationToken [#we443ca7]
-.NET4.0 から CancellationToken を利用したタスクのキャン...
--タスク開始前にトークンがキャンセルされてるかのチェック...
--ThrowIfCancellationRequestedメソッドでOperationCanceled...
---タスクの本体がOCEに含まれるキャンセルトークンも監視し...
---同じだったら、タスクのステータスはCanceledになる(普通...
-参考
--【C#】Taskをキャンセルする - vaguely~
http://mslgt.hatenablog.com/entry/2017/10/08/091841
--【C#】タスクのキャンセル方法 - Tumbling Dice~
http://outofmem.hatenablog.com/entry/2014/04/02/014201
--[[C# Taskの引数に使うCancellationTokenは何に使われてい...
---c# - Cancellation token in Task constructor: why? - St...
https://stackoverflow.com/questions/3712939/cancellation-...
--Microsoft Docs
---マネージド スレッドのキャンセル~
https://docs.microsoft.com/ja-jp/dotnet/standard/threadin...
---CancellationToken Struct (System.Threading)~
https://docs.microsoft.com/ja-jp/dotnet/api/system.thread...
--Qiita
---Cancellation Token について調べてみる~
https://qiita.com/TsuyoshiUshio@github/items/b2d23b37b410...
---非同期で複数処理を実行し、対話式で制御する~
https://qiita.com/haminiku/items/cc299c1ed94d7ba3f9ec
**同期コンテキストの利用オプション [#k890ba74]
***ContinueWith [#vb891159]
-複数のタスクを継続に連結し、時間のかかる同期コンテキスト...
-参考
--方法: 複数のタスクを継続に連結する~
https://msdn.microsoft.com/ja-jp/library/dd537612.aspx
--Task.ContinueWith メソッド (System.Threading.Tasks)~
https://msdn.microsoft.com/ja-jp/library/system.threading...
***ConfigureAwait [#vb891159]
-同期コンテキストを使用するか・しないかを制御できる。
-参考
--Task.ConfigureAwait メソッド (Boolean) (System.Threadin...
https://msdn.microsoft.com/ja-jp/library/system.threading...
*ガイドライン [#c3aa7761]
以下の参考資料から、ガイドラインを纏めてみた。
**一般的に [#l7670f2c]
***戻り値がvoidのメソッドを非同期呼び出ししない。 [#f9d2c...
-呼び出し側でタスクの終了を検出することができない。
-タスクで発生した例外を呼び出し側で補足することができない。
-例外:イベントハンドラはOK(そもそもイベントハンドラ用)...
→ 前項の理由のような挙動でも問題ないが無いため。
***Task.Wait() を使う場合は注意する [#t55295a3]
-Task.Wait()は、非同期処理を待機するため、デッドロックの...
-実行する非同期Taskの前に、Task.Waitが割り込むとデッドロ...
以下、デッドロックのサンプル。
-UIの場合のサンプル~
同期コンテキストであるWindowsメッセージングキューに、~
Task.Wait、非同期Taskの順でキューイングされるため~
前者が後者の完了を待ち続け、後者が何時迄も実行されないた...
--[C#] 同期メソッドから非同期メソッドを呼び出すと~
アプリケーションがフリーズする - 非同期メソッド呼び出しに...
https://www.ipentec.com/document/document.aspx?page=cshar...
-ASP.NETの場合のサンプル~
同期コンテキストであるI/O完了ポートに、~
Task.Result(≒Task.Wait)、非同期Taskの順でキューイングされ...
前者が後者の完了を待ち続け、後者が何時迄も実行されないた...
--ASP.NET で非同期 (Async) を乗りこなす – Tsmatz~
https://blogs.msdn.microsoft.com/tsmatsuz/2012/05/08/asp-...
---await で Post された同期処理は、GetHeader().Result(非...
---同時に、GetHeader().Result(非同期処理) は、この Post...
-参考
--Task.Waitの問題点~
http://outside6.wp.xdomain.jp/2016/08/06/post-343/
--async/await ~非同期なライブラリは楽じゃない~ - 飽きっ...
http://qwerty2501.hatenablog.com/entry/2014/04/24/235849
**ライブラリの場合 [#g2ae71ea]
ざっくり、以下のガイドラインに従う。
-基本的に同期で実装する。
-非同期は、async/awaitを使用しない従来の非同期で実装する。
--コールスタックの下位でasyncを使うと、呼出側もasyncの使...
--そのため、一番外側までasyncを使うようにする必要がある。
--しかし、動作を変えることができないケースがあるので、~
Task.Waitやその他のブロック手段を使って同期を取るしかなく...
-async/awaitを使用する場合、
--Taskを返すだけにして、Task.Runは使わないようにする。
--ライブラリ内でawaitする場合は、ConfigureAwait(false)を...
詳しくは、下記を参照のこと。
***ライブラリ内でTask.Runを使わない [#d1bc9150]
-アンチパターン
public static async Task FetchFileAsync(int fileNum)
{
await Task.Run(() =>
{
var contents = IO.DownloadFile();
Console.WriteLine("Fetched file #{0}: {1}", file...
});
}
-理由:
--ライブラリがグローバル共有リソースであるThreadPoolを使...
--ライブラリは、実行コンテキストが不明なので、ThreadPool...
ライブラリ開発者ではなくアプリケーション開発者がするべき。
--ライブラリが非同期メソッドを提供するのはネイティブ非同...
---ネイティブ非同期メソッドはスレッドプールを使った別スレ...
---I/Oなどの待ちに対してスレッドを空けて同時実効性を高め...
-サーバでのTask.Run
--サーバでTask.Runを使わない。
--理由:
---Task.Runはスケーラビリティが求められるサーバでは不適切
---I/Oバウンドの場合(CPUバウンドでない場合)だけ、非同期...
この決定はライブラリ開発者ではなくアプリケーション開発者...
-クライアントでのTask.Run
--クライアントでも、Task.Runを使わない。
--理由:
---クライアント側ではTask.Runを使う理由がたくさんある。
---しかし前述にあるように、実行コンテキストが不明なので、...
-例外
--例外: マルチスレッドとWinJS~
WinJSは新しいバックグラウンドスレッドを作ることができない...
--例外: Stream.ReadAsync~
---ある種のストリームはこれをサポートしない。
---サポートされない場合は、基底クラス(Steamクラス)でTas...
***Waitを使う同期メソッドで非同期メソッドをラップしない [...
-これは以下の様なユーザの仮定に基づくため。
--同期バージョンの方が非同期バージョンより高速(と言う仮...
非同期バージョンより高速な同期バージョンを提供できない場...
---両方のバージョンを提供する(=ラップを提供する)理由が...
---非同期バージョンを呼び出すときにTask.Waitを使って同期...
--同期バージョンは、UIスレッドで実行しても安全(と言う仮...
非同期メソッドをラップした同期メソッドがTask.Waitを使って...
-従って、推奨は、
--メソッドが同期処理を行うなら、同期バージョンだけを提供...
--メソッドが非同期処理を行うなら、
---非同期バージョンだけを提供する。
---高速に動作するデッドロックを起こさない同期メソッドのみ...
***デッドロックと同期コンテキスト [#i6758c6b]
-基本的にはライブラリ内でawaitする場合はConfigureAwait(fa...
--性能的に早くなる。
--UIの場合の同期コンテキストであるWindowsメッセージングキ...
同期コンテキストによっては、デッドロックさせる可能性が高...
-ConfigureAwait(false)すると元のスレッド(主にUIスレッド)...
必要に応じて、同期コンテキストによる動作スレッドの切り替...
// UIスレッドの同期コンテキストをキャッシュする
SynchronizationContext syncContext = SynchronizationCont...
//.ConfigureAwait(false)でUIスレッドに戻さない
await HeavyWorkAsync().ConfigureAwait(false);
// UIスレッドの同期コンテキストにディスパッチする。
syncContext.Post(state =>
{
// 何からの処理。
}, null);
***性能についての考察 [#y1e4a6ca]
-実行コンテキストをコピーする。
--ログイン・ユーザやカルチャ情報など[[偽装>サービス・タス...
CallContext.SetLocalDataを使用して、実行コンテキストをコ...
--この処理は非同期呼び出しに少量の性能コストを追加する。
-ループ内で呼び出さない。
--asyncを使ったメソッドはTaskの生成やTaskの実行管理のため...
--従って、ライブラリのユーザにはループ内で呼び出さないよ...
-参考
--Async/Await- パフォーマンス上のオーバーヘッドと他の落と...
http://www.infoq.com/jp/news/2013/07/async-await-pitfalls
---Async/Await - Best Practices in Asynchronous Programmi...
http://msdn.microsoft.com/en-us/magazine/jj991977.aspx
***メモリについての考察 [#j268c8a9]
非同期メソッドの呼び出しは次の3つのメモリ確保処理を生む。
-◯:ローカルの変数を保存するためのステートマシン
-◯:継続のためのデリゲート
-結果を返すためのタスク
◯が付与された、ステートマシンとデリゲートはawaitキーワー...
ランタイムに現れたときに作成されるため、同期処理と比べる...
**参考 [#w53a7cb8]
***落とし穴 [#r5c84421]
-C#の非同期の落とし穴~
https://www.infoq.com/jp/news/2013/04/async-csharp-fsharp
-Async in C# and F#: Asynchronous gotchas in C# (Japanese...
https://gist.github.com/pocketberserker/5565303
-neue cc
--asyncの落とし穴Part2, SynchronizationContextの向こう側~
http://neue.cc/2013/07/02_412.html
--asyncの落とし穴Part3, async voidを避けるべき100億の理由~
http://neue.cc/2013/10/10_429.html
***ガイドライン [#x2b8b132]
-TAP (Task-based Asynchronous Pattern) 非同期メソッドのガ...
http://qiita.com/chocolamint/items/ed4999cccf011653cb78
-.NETで非同期ライブラリを正しく実装する~
https://www.infoq.com/jp/articles/Async-API-Design
--Creating Async Libraries That Are Modular, Reusable and...
in Microsoft Visual C# and Visual Basic | TechEd Europe 2...
https://channel9.msdn.com/Events/TechEd/Europe/2013/DEV-B...
-Tasks are (still) not threads and async is not parallel~
http://blogs.msdn.com/b/benwilli/archive/2015/09/10/tasks...
*参考 [#l0e9a88c]
-Insider.NET > 業務アプリInsider~
--連載:C# 5.0&VB 11.0新機能「async/await非同期メソッド...
http://www.atmarkit.co.jp/ait/subtop/features/dotnet/app/...
-Taskを極めろ!async/await完全攻略 - Qiita~
http://qiita.com/acple@github/items/8f63aacb13de9954c5da
-ASP.NET で非同期 (Async) を乗りこなす | Tsmatz~
https://tsmatz.wordpress.com/2012/05/08/asp-net-mvc-async/
**xin9le.net [#aab910a7]
-TPL入門~
http://blog.xin9le.net/entry/tpl-intro
-非同期メソッド入門~
http://blog.xin9le.net/entry/async-method-intro
**MakCraft、徒然なブログ [#o74f57f1]
-非同期処理(インデックス) - MakCraft~
http://www.makcraft.com/devref/26-asynchronous-processing...
***非同期処理 [#def5ad7d]
-(その1)~
http://www.makcraft.com/blog/meditation/2013/03/22/asynch...
-(その2)~
http://www.makcraft.com/blog/meditation/2013/03/23/asynch...
-(その3)~
http://www.makcraft.com/blog/meditation/2013/03/23/asynch...
-(その4)~
http://www.makcraft.com/blog/meditation/2013/03/24/asynch...
-(その5)~
http://www.makcraft.com/blog/meditation/2013/04/02/asynch...
***プロデューサー/コンシューマー パターン [#j1d76f27]
-プロデューサー/コンシューマー パターン~
http://www.makcraft.com/blog/meditation/2013/03/24/produc...
-を利用したサーバー側接続処理~
http://www.makcraft.com/blog/meditation/2013/04/04/server...
-を利用した IPv4 及び IPv6 接続待ち~
http://www.makcraft.com/blog/meditation/2013/04/06/listen...
----
Tags: [[:プログラミング]], [[:.NET開発]]
終了行:
「[[マイクロソフト系技術情報 Wiki>http://techinfoofmicros...
-[[戻る>非同期処理]]
* 目次 [#l24f314e]
#contents
*概要 [#d9ab14bf]
**はじめに [#rb3ca86b]
-async/awaitの登場で、マルチスレッド処理として実装しなく...
非同期処理を同期型処理と、ほぼ変わらない記述で容易に実装...
-awaitの意味は、
--スレッドを止めずノンブロッキングで
--非同期から同期に復帰する
>という意味らしい。
-実際、async/awaitはそういう動きをする。~
--スレッドやWindowsメッセージングキューでTask化される。~
昔懐かしい、[[ノンプリエンプティブ・マルチタスク]](Win3.1...
--しかし、その実態はとても複雑(詳しくは[[コチラ>#nc34461...
---内部がどう動いているか詳しく把握しないとシステムは安定...
---中身をシッカリ理解して使用している人が少ないので注意が...
**用途 [#kb0ddc1e]
主に、非同期処理(≠並列処理)を簡単に(同期処理的に)実装...
-UIスレッドからのサーバ呼出のハングアップを防止するために...
-または、内部的には、UIスレッドから、時間のかかるバックグ...
(ネットワーク バインドまたは I/O バインドの処理)を分離...
-Webサーバのスレッド枯渇を防ぐ[[非同期Controller>ASP.NET ...
-並列実行処理を実装するための基盤ではない。
--[[Fire & Forget>#hc2dffee]]やTask.WhenAllで並列実行処理...
await、Task.Wait()の"待ち合わせ"までがセットになっている...
そもそも、並列実行処理を実装することに特化した基盤ではな...
(非同期タスクを作成して待つ処理を同期的に書ける仕組みと...
--並列実行処理を実装する場合は、Threadや、ThreadPoolを使...
**使い方 [#l81605a4]
async/awaitの登場で、非同期処理を同期型処理と、ほぼ変わら...
-asyncで修飾したTaskを返す非同期メソッドから、awaitステー...
-若しくは、Task.Run()で実行して、Task.Wait()で待ち合わせ...
しかし、デバッグの時は非同期で実行されていることを意識す...
(しかも、かなり特殊な。同期コンテキスト毎に動作も大きく...
**仕組み [#kaa7ba64]
-非同期化からのノンブロッキングの復帰には同期コンテキスト...
-同期コンテキストにはWindowsメッセージングキュー、ThreadP...
-仕組みの詳細については[[コチラ>#nc344611]]を参照。
async/await]]は、TAP(Task-based Asynchronous Pattern)の...
async/awaitは、
-メッセージ(番号)のような制約のある単純固定長値のキューで...
実行コードの任意のコード断片そのものをキュー(同期コンテ...
-.NET 3.5用のasync/await互換NuGetパッケージでは、~
.NET 4のTask互換クラスを、内部をBeginInvoke等で実装して、...
**余談 [#ef267401]
async/awaitの夫々の意味。
-async修飾子~
asyncは、呼び出し元と同じ同期コンテキストで実行されること...
-await演算子~
asyncをawaitすると、スレッドを止めずに同期コンテキストで...
この動作は想像し難いが、具体的には、
-同じ同期コンテキスト(Windowsメッセージングキュー)に
-コールバックを順番に並べる(Control.BeginInvoke()的な)。
というイメージ。
-・・・結局、APM、EAPと同じ技術(同期コンテキスト)を使っ...
-なお、同期コンテキストの種類によって、動きも異なる。
--同期コンテキストはキュー的なもので実装されている。~
例えば、前述の、
---Windowsメッセージングキュー、
---ThreadPool
---I/O 完了ポート
---, etc.
--なので、言葉尻だけで動作を想像し難く、~
[[利用の際は注意が必要になってくる>#c3aa7761]]。
*実装方法 [#je886ba3]
**タスク分割方法 [#gb4b4431]
await(Task.Run)を切れ目として、~
プログラマが意識して時間のかかるバックグラウンド処理~
(ネットワーク バインドまたは I/O バインドの処理)を分割...
***await [#d6f183d7]
-await前の処理はフォアグラウンド的に実行される。
-awaitで呼び出す非同期メソッドはバックグラウンド的に実行...
-await後の処理は、コールバックとして実装せずにフォアグラ...
--厳密に言うとフォアグラウンドに復帰ではなく、~
プログラムのコード上、非同期処理の後続処理に復帰する。~
--例えば、[[非同期Controller>ASP.NET MVCの用語#lc319892]]...
---非同期スレッド側で実行され、最後にリクエストを受け付け...
---この動作は、システム的には、フォアグラウンドに復帰する...
***Task.Run ~ Task.Wait() [#t097d303]
-Task.Run前の処理はフォアグラウンド的に実行される。
-Task.Run()で呼び出す非同期メソッドはバックグラウンド的に...
-Task.Wait()後の処理は、コールバックとして実装せずして、...
-Task.Waitが呼ばれるとスレッドはTaskが終わるまで待機する。
-これらの動きの詳細は、同期コンテキストによって異なってく...
-また、Task.Waitを使用すると、同期コンテキスト上、~
実行する非同期Taskの前に、Task.Waitが割り込むとデッドロッ...
**非同期メソッドの戻り値 [#b43ff41c]
***void型 [#w5cf9ec2]
[[Fire & Forget>#hc2dffee]]の場合、戻り値は不要。
***Task型 [#t98c2e31]
[[Awaitable>#v7df61f1]]の場合、
-戻り値の無い非同期メソッドを実装する場合、Task型の戻り値...
-基本的に、returnを書く必要はない。
-しかし、非同期メソッド内で非同期処理を呼び出さない場合、~
[[Task.FromResult>#vfa22973]]で、完了状態のTaskを生成する...
await Task.FromResult(0);
await Task.FromResult(default(object));
***Task<T>型 [#td2f6464]
[[Awaitable>#v7df61f1]]の場合、
-T型の戻り値の有る非同期メソッドを実装する場合、Task<T>型...
-戻り値はTask<T>型だが、awaitした後、Tの型の値をreturnす...
int ret = await XXXXAsync();
return ret;
-しかし、非同期メソッド内で非同期処理を呼び出さない場合、~
[[Task.FromResult>#vfa22973]]で、完了状態のTask<T>を生成...
await Task.FromResult(new T());
***Task.FromResult [#vfa22973]
Task.FromResultを使用すると、完了状態のTaskを生成すること...
-以下のようなケースで利用する。
--戻り値のTaskが長いコード パスを実行することなく、直ぐ完...
--インターフェイス上はTaskを返すが、メソッド内で非同期処...
-詳細については、下記を参照のこと。
--Task.FromResult(TResult) メソッド (TResult) (System.Thr...
https://msdn.microsoft.com/ja-jp/library/hh194922.aspx
--c# - If my interface must return Task what is the best ...
https://stackoverflow.com/questions/13127177/if-my-interf...
**非同期メソッドの呼び出し [#s278988c]
***await演算子 [#z7b2e8a4]
-Task の実行が完了したら、待機せずに、~
フォアグラウンドに復帰する風な動きを見せる。
--await 非同期メソッド()
--await Task.Run()
-await演算子の使い方
--非同期メソッドを呼び出すときに、await演算子を利用する。
--メソッド内でawait演算子を利用する場合、async修飾子でメ...
--await演算子は、async修飾子の付くメソッドの中で1つ以上...
***Task.Run()・Task.Wait()、Task.WhenAll()メソッド [#l8b4...
-Task.Run()メソッド
--非同期メソッドを実行してTask、Task<TResult>を返す。
-Task.Wait()
--Task、Task<TResult>の実行が完了するまで待機する。
--async/awaitと異なり、同期コンテキストで同期せず、~
待機(ブロック)した後にフォアグラウンドに復帰する。
-Task.WhenAll()
--メソッドで複数のタスクを待機するタスクを取得する。
--このTaskをTask.Wait()するとTask毎の~
例外をAggregateException型として取得可能。
**非同期メソッドの作り方 [#rc951c69]
***参考 [#uc071d5f]
- [.NET Framework 4/4.5][C# 5] 非同期で動くビジネスロジッ...
: biac の それさえもおそらくは幸せな日々@nifty~
http://bluewatersoft.cocolog-nifty.com/blog/2011/12/net-f...
-Task.Start()、Task.Factory.StartNew()、Task.Run()
--Task クラスと TaskFactory クラス~
http://www.kanazawa-net.ne.jp/~pmansato/parallel/parallel...
--Task.Start()とTask.Run()とTask.Factory.StartNew()の違い...
http://fromfulltofree.blog.fc2.com/blog-entry-7.html
- [雑記] スレッド プールとタスク~
C# によるプログラミング入門 | ++C++; // 未確認飛行 C~
http://ufcpp.net/study/csharp/misc_task.html
-Provide an asynchronous version method for call the B-la...
from the action method of asynchronous controller.~
· Issue #216 · OpenTouryoProject/OpenTouryo~
https://github.com/OpenTouryoProject/OpenTouryo/issues/216
*詳細 [#nc344611]
ここでは、
-「非同期メソッドの種類」と
-「同期コンテキスト」の
組み合わせによって、await後の処理が、~
どのように実行されるのかについて説明する。
-参考
--async/awaitと同時実行制御 | ++C++; // 未確認飛行 C ブロ...
https://ufcpp.wordpress.com/2012/11/12/asyncawait%E3%81%A...
---An other world awaits you~
http://www.slideshare.net/ufcpp/an-other-world-awaits-you
**非同期メソッドの種類 [#yc35ca64]
非同期メソッドには、2種類ある。
-[[Fire & Forget>#hc2dffee]]~
戻り値がvoidのメソッド
-[[Awaitable>#v7df61f1]]~
戻り値がTask(もしくはTask<T>)のメソッド
***Fire & Forget [#hc2dffee]
非同期メソッドでもreturn文を書く必要が無い。
戻り値がvoidなので非同期以降がフォアグラウンドに復帰しな...
-非同期呼び出しで投げっぱなす場合。
-具体的には、GUIアプリケーションのイベント・ハンドラに適...
-上記以外の用途での利用は意味もなく、ハマる原因になるので...
***Awaitable [#v7df61f1]
非同期メソッドは、Task、Task<T>をリターンする。
戻り値がTask(もしくはTask<T>)なので、await演算子かWait(...
以降に実装された非同期以降がフォアグラウンドに復帰する。
-非同期呼び出しの呼び出し元で
--awaitで、非同期以降をフォアグラウンドに復帰させる場合。
--Task.Wait()で呼び出し元が非同期メソッドの完了を待機する...
**同期コンテキスト [#je52c46b]
実行環境によって持つ同期コンテキストの種類が異なる。
***GUIアプリケーション [#yc5c5030]
GUIアプリケーションでの同期コンテキストは~
「Windowsメッセージングキュー(Control.Invoke、.BeginInvo...
-Fire & Forget~
GUIアプリケーションのawaitの次の処理は、~
同期コンテキストのControl.BeginInvokeによって、~
UIスレッド上でシーケンシャルに実行される。
-Awaitable~
該当なし?Control.Invokeでは?
***Consoleアプリケーション [#ibd79536]
Consoleアプリケーションでの同期コンテキストは「null」にな...
-Fire & Forget~
非推奨(Threadや、ThreadPoolを使用すればイイ)
-Awaitable
--Consoleアプリケーション内のawaitの次の処理が実行される...
--ただし、処理自体は、(記述した順に)シーケンシャルに実...
***ThreadPool [#cf19c6b3]
Task.Runを使用した場合の同期コンテキストは、~
マルチスレッド環境下の「ThreadPool」になる。
-Fire & Forget~
非推奨(Threadや、ThreadPoolを使用すればイイ)
-Awaitable
--Task.Run内のawaitの次の処理が実行されるスレッドは一意で...
--且つ、Task.Run内のawaitの次の処理は、UIスレッドに戻らな...
--ただし、処理自体は、(記述した順に)シーケンシャルに実...
***ASP.NET [#s4df3070]
ASP.NETアプリケーションでの同期コンテキストは~
マルチスレッド環境下の「System.Threading.SynchronizationC...
-Fire & Forget~
非推奨(Threadや、ThreadPoolを使用すればイイ)
-Awaitable
--ASP.NETアプリケーションのawaitの次の処理が実行されるス...
--ただし、処理自体は、(記述した順に)シーケンシャルに実...
--HttpContext等の保持、非同期処理が全て終わるまで、レスポ...
--最終的に結果は、リクエストを受け付けたスレッドにバイン...
詳しくは、[[非同期Controller>ASP.NET MVCの用語#lc319892]]...
この辺の
-asp.net mvc - MVC Action Filters Collection was modified;~
enumeration operation may not execute - Stack Overflow~
http://stackoverflow.com/questions/29429526/mvc-action-fi...
スタック・トレースを見ると、
-「SynchronizationContext」と
-「AsyncControllerActioninvoker」は
同じ事らしいと解る。
なお、恐らく、これらの同期コンテキストは、~
I/O完了ポート(IOCP)= ノンブロッキングI/Oであると思われ...
-Can ASP.NET MVC's AsyncController be used to service lar...
concurrent hanging requests (long poll)? - Stack Overflow~
http://stackoverflow.com/questions/4982882/can-asp-net-mv...
***並列実行 [#k847f44a]
-GUI以外の同期コンテキストでFire & Forgetを実行した場合(...
-Task.WhenAllで複数のTaskをTask.Wait()した場合(ThreadPoo...
並列実行を始めるので、~
特に、Consoleアプリケーションの同期コンテキスト(null)の...
新規に[[同期処理>#z135f913]]の実装が必要になることがある。
*同期 [#w87411f4]
async/awaitは非同期呼び出しで投げっぱなした後に、~
同期コンテキストにより同期される方式のため、同期をあまり...
同期コンテキストによっては、同期を行う必要があるため、以...
**仕組みから [#ab98fed9]
スレッドを使用した処理を記述しないが、
分割されたタスクは、
-同一スレッドで動作することも
-別スレッドで動作することもある。
このため、一連の処理が(分割されたタスクが)、
-異なるスレッドで実装される保証は無い。
-同じスレッドで実行される保証も無い。
**スレッド同期ツールキットは使用不可 [#sdd9c0ad]
従って、スレッド同期のlock等は無意味。~
従来のスレッド同期ツールキットは使用不可。
***lock/mutex/semaphoreはtaskで全て使用禁止 [#offf1b54]
旧プログラムで、
+スレッド・アフィニティのあるロック機構(lock/mutex/semap...
+awaitを使用して修正変更をしたい場合(await演算子を含むコ...
スレッド・アフィニティのないロック機構を使用する。
***WaitFor[Single|Multi]Objectは例外的に使用可 [#z135f913]
Win32の待機関数のWaitFor[Single|Multi]Objectは例外的に使...
これらの待機関数は、
-スレッド・アフィニティではなく、
-「状態変化」(ノンシグナル状態からシグナル状態への変化)を
待つ関数であるためと考える。
-スレッド・アフィニティのないロック機構
--.NET TIPS:非同期:awaitを含むコードをロックするには?...
http://www.atmarkit.co.jp/ait/spv/1411/11/news117.html
---SemaphoreSlim.WaitAsync関数もasync/awaitする。
---Semaphoreによるlockさえ、タスクとして分割されて待機/実...
--ThreadPool クラス (System.Threading)~
https://msdn.microsoft.com/ja-jp/library/system.threading...
---ThreadPool.RegisterWaitForSingleObject メソッド (Syste...
https://msdn.microsoft.com/ja-jp/library/system.threading...
--EventWaitHandle クラス (System.Threading)~
https://msdn.microsoft.com/ja-jp/library/system.threading...
---AutoResetEvent クラス (System.Threading)~
https://msdn.microsoft.com/ja-jp/library/system.threading...
---ManualResetEvent クラス (System.Threading)~
https://msdn.microsoft.com/ja-jp/library/system.threading...
*その他 [#r19de18d]
**進捗報告 [#p80858da]
上記の仕組みで動いているとすると、進捗報告をどう実装する...
以下を見ると、Progressクラス、IProgress<T>インターフェー...
-非同期メソッド - C# によるプログラミング入門 | ++C++; //...
http://ufcpp.net/study/csharp/sp5_async.html#cancel
-.NET TIPS:WPF/Windowsフォーム:~
時間のかかる処理をバックグラウンドで実行するには?(async...
http://www.atmarkit.co.jp/ait/articles/1512/02/news019.html
詳しい仕組みは不明だが、GUI上で動作しているため、~
同期コンテキストのControl.Invoke、.BeginInvokeを使用して...
**CancellationToken [#we443ca7]
-.NET4.0 から CancellationToken を利用したタスクのキャン...
--タスク開始前にトークンがキャンセルされてるかのチェック...
--ThrowIfCancellationRequestedメソッドでOperationCanceled...
---タスクの本体がOCEに含まれるキャンセルトークンも監視し...
---同じだったら、タスクのステータスはCanceledになる(普通...
-参考
--【C#】Taskをキャンセルする - vaguely~
http://mslgt.hatenablog.com/entry/2017/10/08/091841
--【C#】タスクのキャンセル方法 - Tumbling Dice~
http://outofmem.hatenablog.com/entry/2014/04/02/014201
--[[C# Taskの引数に使うCancellationTokenは何に使われてい...
---c# - Cancellation token in Task constructor: why? - St...
https://stackoverflow.com/questions/3712939/cancellation-...
--Microsoft Docs
---マネージド スレッドのキャンセル~
https://docs.microsoft.com/ja-jp/dotnet/standard/threadin...
---CancellationToken Struct (System.Threading)~
https://docs.microsoft.com/ja-jp/dotnet/api/system.thread...
--Qiita
---Cancellation Token について調べてみる~
https://qiita.com/TsuyoshiUshio@github/items/b2d23b37b410...
---非同期で複数処理を実行し、対話式で制御する~
https://qiita.com/haminiku/items/cc299c1ed94d7ba3f9ec
**同期コンテキストの利用オプション [#k890ba74]
***ContinueWith [#vb891159]
-複数のタスクを継続に連結し、時間のかかる同期コンテキスト...
-参考
--方法: 複数のタスクを継続に連結する~
https://msdn.microsoft.com/ja-jp/library/dd537612.aspx
--Task.ContinueWith メソッド (System.Threading.Tasks)~
https://msdn.microsoft.com/ja-jp/library/system.threading...
***ConfigureAwait [#vb891159]
-同期コンテキストを使用するか・しないかを制御できる。
-参考
--Task.ConfigureAwait メソッド (Boolean) (System.Threadin...
https://msdn.microsoft.com/ja-jp/library/system.threading...
*ガイドライン [#c3aa7761]
以下の参考資料から、ガイドラインを纏めてみた。
**一般的に [#l7670f2c]
***戻り値がvoidのメソッドを非同期呼び出ししない。 [#f9d2c...
-呼び出し側でタスクの終了を検出することができない。
-タスクで発生した例外を呼び出し側で補足することができない。
-例外:イベントハンドラはOK(そもそもイベントハンドラ用)...
→ 前項の理由のような挙動でも問題ないが無いため。
***Task.Wait() を使う場合は注意する [#t55295a3]
-Task.Wait()は、非同期処理を待機するため、デッドロックの...
-実行する非同期Taskの前に、Task.Waitが割り込むとデッドロ...
以下、デッドロックのサンプル。
-UIの場合のサンプル~
同期コンテキストであるWindowsメッセージングキューに、~
Task.Wait、非同期Taskの順でキューイングされるため~
前者が後者の完了を待ち続け、後者が何時迄も実行されないた...
--[C#] 同期メソッドから非同期メソッドを呼び出すと~
アプリケーションがフリーズする - 非同期メソッド呼び出しに...
https://www.ipentec.com/document/document.aspx?page=cshar...
-ASP.NETの場合のサンプル~
同期コンテキストであるI/O完了ポートに、~
Task.Result(≒Task.Wait)、非同期Taskの順でキューイングされ...
前者が後者の完了を待ち続け、後者が何時迄も実行されないた...
--ASP.NET で非同期 (Async) を乗りこなす – Tsmatz~
https://blogs.msdn.microsoft.com/tsmatsuz/2012/05/08/asp-...
---await で Post された同期処理は、GetHeader().Result(非...
---同時に、GetHeader().Result(非同期処理) は、この Post...
-参考
--Task.Waitの問題点~
http://outside6.wp.xdomain.jp/2016/08/06/post-343/
--async/await ~非同期なライブラリは楽じゃない~ - 飽きっ...
http://qwerty2501.hatenablog.com/entry/2014/04/24/235849
**ライブラリの場合 [#g2ae71ea]
ざっくり、以下のガイドラインに従う。
-基本的に同期で実装する。
-非同期は、async/awaitを使用しない従来の非同期で実装する。
--コールスタックの下位でasyncを使うと、呼出側もasyncの使...
--そのため、一番外側までasyncを使うようにする必要がある。
--しかし、動作を変えることができないケースがあるので、~
Task.Waitやその他のブロック手段を使って同期を取るしかなく...
-async/awaitを使用する場合、
--Taskを返すだけにして、Task.Runは使わないようにする。
--ライブラリ内でawaitする場合は、ConfigureAwait(false)を...
詳しくは、下記を参照のこと。
***ライブラリ内でTask.Runを使わない [#d1bc9150]
-アンチパターン
public static async Task FetchFileAsync(int fileNum)
{
await Task.Run(() =>
{
var contents = IO.DownloadFile();
Console.WriteLine("Fetched file #{0}: {1}", file...
});
}
-理由:
--ライブラリがグローバル共有リソースであるThreadPoolを使...
--ライブラリは、実行コンテキストが不明なので、ThreadPool...
ライブラリ開発者ではなくアプリケーション開発者がするべき。
--ライブラリが非同期メソッドを提供するのはネイティブ非同...
---ネイティブ非同期メソッドはスレッドプールを使った別スレ...
---I/Oなどの待ちに対してスレッドを空けて同時実効性を高め...
-サーバでのTask.Run
--サーバでTask.Runを使わない。
--理由:
---Task.Runはスケーラビリティが求められるサーバでは不適切
---I/Oバウンドの場合(CPUバウンドでない場合)だけ、非同期...
この決定はライブラリ開発者ではなくアプリケーション開発者...
-クライアントでのTask.Run
--クライアントでも、Task.Runを使わない。
--理由:
---クライアント側ではTask.Runを使う理由がたくさんある。
---しかし前述にあるように、実行コンテキストが不明なので、...
-例外
--例外: マルチスレッドとWinJS~
WinJSは新しいバックグラウンドスレッドを作ることができない...
--例外: Stream.ReadAsync~
---ある種のストリームはこれをサポートしない。
---サポートされない場合は、基底クラス(Steamクラス)でTas...
***Waitを使う同期メソッドで非同期メソッドをラップしない [...
-これは以下の様なユーザの仮定に基づくため。
--同期バージョンの方が非同期バージョンより高速(と言う仮...
非同期バージョンより高速な同期バージョンを提供できない場...
---両方のバージョンを提供する(=ラップを提供する)理由が...
---非同期バージョンを呼び出すときにTask.Waitを使って同期...
--同期バージョンは、UIスレッドで実行しても安全(と言う仮...
非同期メソッドをラップした同期メソッドがTask.Waitを使って...
-従って、推奨は、
--メソッドが同期処理を行うなら、同期バージョンだけを提供...
--メソッドが非同期処理を行うなら、
---非同期バージョンだけを提供する。
---高速に動作するデッドロックを起こさない同期メソッドのみ...
***デッドロックと同期コンテキスト [#i6758c6b]
-基本的にはライブラリ内でawaitする場合はConfigureAwait(fa...
--性能的に早くなる。
--UIの場合の同期コンテキストであるWindowsメッセージングキ...
同期コンテキストによっては、デッドロックさせる可能性が高...
-ConfigureAwait(false)すると元のスレッド(主にUIスレッド)...
必要に応じて、同期コンテキストによる動作スレッドの切り替...
// UIスレッドの同期コンテキストをキャッシュする
SynchronizationContext syncContext = SynchronizationCont...
//.ConfigureAwait(false)でUIスレッドに戻さない
await HeavyWorkAsync().ConfigureAwait(false);
// UIスレッドの同期コンテキストにディスパッチする。
syncContext.Post(state =>
{
// 何からの処理。
}, null);
***性能についての考察 [#y1e4a6ca]
-実行コンテキストをコピーする。
--ログイン・ユーザやカルチャ情報など[[偽装>サービス・タス...
CallContext.SetLocalDataを使用して、実行コンテキストをコ...
--この処理は非同期呼び出しに少量の性能コストを追加する。
-ループ内で呼び出さない。
--asyncを使ったメソッドはTaskの生成やTaskの実行管理のため...
--従って、ライブラリのユーザにはループ内で呼び出さないよ...
-参考
--Async/Await- パフォーマンス上のオーバーヘッドと他の落と...
http://www.infoq.com/jp/news/2013/07/async-await-pitfalls
---Async/Await - Best Practices in Asynchronous Programmi...
http://msdn.microsoft.com/en-us/magazine/jj991977.aspx
***メモリについての考察 [#j268c8a9]
非同期メソッドの呼び出しは次の3つのメモリ確保処理を生む。
-◯:ローカルの変数を保存するためのステートマシン
-◯:継続のためのデリゲート
-結果を返すためのタスク
◯が付与された、ステートマシンとデリゲートはawaitキーワー...
ランタイムに現れたときに作成されるため、同期処理と比べる...
**参考 [#w53a7cb8]
***落とし穴 [#r5c84421]
-C#の非同期の落とし穴~
https://www.infoq.com/jp/news/2013/04/async-csharp-fsharp
-Async in C# and F#: Asynchronous gotchas in C# (Japanese...
https://gist.github.com/pocketberserker/5565303
-neue cc
--asyncの落とし穴Part2, SynchronizationContextの向こう側~
http://neue.cc/2013/07/02_412.html
--asyncの落とし穴Part3, async voidを避けるべき100億の理由~
http://neue.cc/2013/10/10_429.html
***ガイドライン [#x2b8b132]
-TAP (Task-based Asynchronous Pattern) 非同期メソッドのガ...
http://qiita.com/chocolamint/items/ed4999cccf011653cb78
-.NETで非同期ライブラリを正しく実装する~
https://www.infoq.com/jp/articles/Async-API-Design
--Creating Async Libraries That Are Modular, Reusable and...
in Microsoft Visual C# and Visual Basic | TechEd Europe 2...
https://channel9.msdn.com/Events/TechEd/Europe/2013/DEV-B...
-Tasks are (still) not threads and async is not parallel~
http://blogs.msdn.com/b/benwilli/archive/2015/09/10/tasks...
*参考 [#l0e9a88c]
-Insider.NET > 業務アプリInsider~
--連載:C# 5.0&VB 11.0新機能「async/await非同期メソッド...
http://www.atmarkit.co.jp/ait/subtop/features/dotnet/app/...
-Taskを極めろ!async/await完全攻略 - Qiita~
http://qiita.com/acple@github/items/8f63aacb13de9954c5da
-ASP.NET で非同期 (Async) を乗りこなす | Tsmatz~
https://tsmatz.wordpress.com/2012/05/08/asp-net-mvc-async/
**xin9le.net [#aab910a7]
-TPL入門~
http://blog.xin9le.net/entry/tpl-intro
-非同期メソッド入門~
http://blog.xin9le.net/entry/async-method-intro
**MakCraft、徒然なブログ [#o74f57f1]
-非同期処理(インデックス) - MakCraft~
http://www.makcraft.com/devref/26-asynchronous-processing...
***非同期処理 [#def5ad7d]
-(その1)~
http://www.makcraft.com/blog/meditation/2013/03/22/asynch...
-(その2)~
http://www.makcraft.com/blog/meditation/2013/03/23/asynch...
-(その3)~
http://www.makcraft.com/blog/meditation/2013/03/23/asynch...
-(その4)~
http://www.makcraft.com/blog/meditation/2013/03/24/asynch...
-(その5)~
http://www.makcraft.com/blog/meditation/2013/04/02/asynch...
***プロデューサー/コンシューマー パターン [#j1d76f27]
-プロデューサー/コンシューマー パターン~
http://www.makcraft.com/blog/meditation/2013/03/24/produc...
-を利用したサーバー側接続処理~
http://www.makcraft.com/blog/meditation/2013/04/04/server...
-を利用した IPv4 及び IPv6 接続待ち~
http://www.makcraft.com/blog/meditation/2013/04/06/listen...
----
Tags: [[:プログラミング]], [[:.NET開発]]
ページ名: