[C#5.0~] async/awaitとTask.Runメソッドを用いた非同期処理のメモ

By | Date : 2015/10/25 ( Last Update : 2016/12/16 ) | 8,120 views

カテゴリ : C# プログラミング タグ: ,

こんにちはー!ニアです。

本記事では、C# 5.0で追加された async / await とTask.Runメソッドを用いた非同期処理の流れをメモとして載せています。

※元々この記事は、C#における非同期処理の健忘帳として書いていましたが、この度はコンソールアプリとGUIアプリにおける処理の流れの違いを図も併せてまとめ、記事をリニューアルすることにしました。

1. 非同期処理の作り方

  • 非同期にしたい処理をTask.Runメソッドの引数にデリーゲートとして指定します。
  • Task.Runメソッドにawaitキーワードを付けて、非同期処理が終わるまで後続の処理を待機するようにします。
  • await付きのメソッドを含むメソッドにはasyncキーワードを付けて、戻り値をTask型にします。
※非同期処理にて、async付きのメソッドの戻り値をTask型にする理由は以下のサイトが参考になります。

 

2. コンソールアプリの場合

まずは、コンソールアプリでの動作の流れを追ってみます。

コンソールアプリでは、Mainメソッドを抜けるとアプリ自体が終了してしまうので、12行目でSumAsyncの処理が終わるまで待機させています。

スレッドのIDを見てみると、SumAsyncメソッド内では「await Task.Run( () => Sum( n ) )」を実行するまでは呼び出し元(Mainメソッド)と同じスレッドであり、Sumメソッド内及び「await Task.Run( () => Sum( n ) )」の後続処理では別のスレッドで処理していることが分かります。

3. GUIアプリの場合

次に、GUIアプリでの動作の流れを追ってみます。

本記事では、例としてWPFアプリで配置したボタンを押した時のイベントにて、非同期処理の動作をテストしてみました。なお、コンソールアプリにできるだけ合わせるために、出力先をデバッグコンソールに指定し、15行目でSumAsyncメソッドの処理が終わるまで、16行目のDebug.WriteLineメソッドの呼び出しを待機させています。

 

スレッドのIDを見てみると、SumAsyncメソッド内では「await Task.Run( () => Sum( n ) )」を実行するまではUIのスレッドであり、Sumメソッド内では別のスレッドで処理しているのはコンソールアプリと似ていますが、「await Task.Run( () => Sum( n ) )」の後からSumAsyncメソッドの終わりまではコンソールアプリとは異なり、UIのスレッドで処理していることが分かります。

 

4. コンソールアプリとGUIアプリで、await付きメソッド前後でスレッドIDが異なっているのはなぜ?

なぜ、await付きのメソッド前後でスレッドIDが、コンソールアプリとGUIアプリで異なるのかというと、それはSynchronizationContext.Currentに設定されているコンテキストが異なるからです。

GUIアプリの場合、UIの更新は必ずUIスレッドで行う必要があるため、SynchronizationContext.CurrentにUIスレッドで行う処理などの情報が格納されています。await付きメソッドの後続処理では、SynchronizationContext.Currentに関連づけられたスレッドで実行されるので、GUIアプリの場合、UIスレッドで実行されます。

非同期処理の結果をUIに反映するというシチュエーションは、よくあるよ~

 

一方、コンソールアプリはというと・・・、

コンソール アプリは同期コンテキストを持っていません。SynchronizationContext.Currentはnullです。

この場合、「awaitは既定の同期コンテキストを使う」ということになっていて、その既定の同期コンテキストはスレッド プールを使います。

async/awaitと同時実行制御 – ++C++; // 未確認飛行 C ブログより引用

Task.Runメソッドで指定したデリゲートはスレッドプール上で実行されるので、await付きメソッドの後続処理はスレッドプール上のスレッドすなわち、Task.Runメソッドで生成したスレッドで実行されると考えられます。

 

 

この記事をシェアする
Chronoir.netのRSSフィードを購読する

About : ニア(Nia)

紅茶とコーヒーが好きな湘南生まれのプログラマー/ITエンジニアです。主にC#/C++/PHPを使ってプログラミングをしています。趣味は写真撮影と音ゲーです。時々イラストを描いています。プログラミングを勉強している方々と仲良くなりたいです! 興味を持っている分野:UWP/Xamarin/Android Wear/WPF/Windows/Visual Studio/WordPress/KUSANAGI/nginx

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*