MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
C Sharpの基礎 - マルチスレッドのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
C Sharpの基礎 - マルチスレッド
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == .NET Framework 4.5で導入されたC# 5.0(Visual Studio 2012) からは、マルチスレッドプログラミングをコンパイラレベルでサポートしている。<br> 具体的には、asyncとawaitというキーワードが導入された。<br> これは、タスクベース非同期パターン(Task-based Asynchronous Pattern、TAP)を実装するものである。<br> <br> このタスクベース非同期パターンでは、処理の開始はMethodNameAsyncという形式をとる。<br> そしてその戻り値を、Task、Task<T>、voidとし、Taskを待つにはawaitを付加する。<br> また、awaitを付加した関数には、asyncを付加する。<br> <br> 下記の例は、Task<int>型を返す非同期関数である。<br> <syntaxhighlight lang="c#"> public async Task<int> MethodAsync() { var iRet = await Task.Run(() => { await Task.Delay(5000); return 0; }); return iRet; } </syntaxhighlight> <br><br> == asyncとawaitの動作 == Taskは、一連の処理をひとまとまりにした単位である。<br> Taskを呼び出した際はマルチスレッドで実行されるようになっており、連続で記述する場合は、記述した個数だけマルチスレッドで並列処理される。<br> <syntaxhighlight lang="c#"> public async Task MethodAsync() { var task1 = Task.Run(() => { // 何か処理1 }); var task2 = Task.Run(() => { // 何か処理2 }); var task12 = Task.WhenAll(task1, task2); var taskAll = task12.ContinueWith(() => { // 何か処理3 }); return await taskAll.ConfigureAwait(false); } </syntaxhighlight> <br><br> == Task.WhenAllとContinueWith == TaskはContinueWith関数を利用して、その後の処理を連続して実行できる。<br> 2つ以上のスレッドを実行して全スレッドの処理が終了した後、続けてスレッドの処理を書く場合は、<br> ContinueWithまたはawaitを使用してスレッドの終了を待つ。<br> <syntaxhighlight lang="c#"> // パターン1 var task1 = Task.Run(() => { // 何か処理 }); var task2 = Task.Run(() => { // 何か処理 }); var task3 = Task.Run(() => { // 何か処理 }); var taskAll = Task.WhenAll(task1, task2).ContinueWith(task3); // awaitは不要 </syntaxhighlight> <br> <syntaxhighlight lang="c#"> // パターン2 var task1 = Task.Run(() => { // 何か処理 }); await task1.ConfigureAwait(false); var task2 = Task.Run(() => { // 何か処理 }); await task2.ConfigureAwait(false); var task3 = Task.Run(() => { // 何か処理 }); await task3.ConfigureAwait(false); </syntaxhighlight> <br> 状況にもよるが、処理が膨大になると可読性が落ちるので、<br> 先に関数で纏めて処理を記述して関数を呼ぶだけでタスク間の関係性が見通せるパターン1の方が良い。<br> <br><br> == ConfigureAwait(false) == GUIアプリケーションでは、以下のように記述すると、簡単にデッドロックが発生する。<br> なぜなら、TaskのWaitメソッドやResultは、元のスレッドへ戻ろうとするからである。<br> <br> 以下の場合、methodAsync().Wait()を呼んだ時点で親スレッドがスリープする。<br> なぜなら、methodAsync()の終了後に親スレッドに戻ろうとするが、既に親スレッドがスリープしているため、<br> 処理を続けることができないからである。<br> その結果、親スレッドは子スレッドを待ち続け、子スレッドは親スレッドに戻ろうとして、デッドロックが発生する。<br> <syntaxhighlight lang="c#"> // デッドロックが起きるサンプルコード(GUIアプリケーションのみ) // コンソールアプリケーションでは正常に動作する public void callMethod() { methodAsync().Wait(); } public async Task methodAsync() { return await Task.Delay(1000); } </syntaxhighlight> <br> 対策として、以下のように記述するとデッドロックが回避できる。(戻るスレッドはどこでもよい場合)<br> <syntaxhighlight lang="c#"> // デッドロックが起きないサンプルコード(GUIアプリケーションのみ) public void callMethod() { methodAsync().Wait(); } public async Task methodAsync() { return await Task.Delay(1000).ConfigureAwait(false); } </syntaxhighlight> <br><br> __FORCETOC__ [[カテゴリ:C_Sharp]]
C Sharpの基礎 - マルチスレッド
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse