明けましておめでとうございます。本年もよろしくお願いいたします。私の作成しているサイト「DOBON.NET」の携帯専用サイト「DOBON.NETモバイル」ができました。Tipsを携帯で読むことができます。「DOBON.NETモバイル」のURLは、https://dobon.net/i/です。「DOBON.NETモバイル」について詳しくはhttps://dobon.net/mobile.htmlをご覧ください。注意この記事の最新版は「.NETのマルチスレッドプログラミング」で公開しています。Frameworkには、デリゲートを使い、メソッドを非同期に(プログラムの実行をブロックせずに)呼び出す簡単な方法が用意されています。この非同期デリゲートを使用すれば、基本的にすべてのメソッドを非同期で呼び出すことができます。パラメータや戻り値の受け渡しも簡単に行えます。この非同期呼び出しにはスレッドプールが使われます。よってマルチスレッドプログラミングやスレッドプールを使う際の注意事項は、非同期デリゲートの使用においても留意する必要があります。スレッドプールについては前回詳しく説明しましたので、そちらをご覧ください。以下に非同期デリゲートを使った簡単な例を示します。この例ではMyMethodメソッドを非同期で呼び出しています。}}[出力結果例]メインスレッド名:メインスレッド非同期処理の開始:ほげほげ処理にかかった時間(ミリ秒):1001上記の例ではMyMethodメソッドを非同期で呼び出すために、まずMyMethodメソッドと同じシグネチャ(パラメータや戻り値の型などの定義)のデリゲート"MyMethodAsyncDelegate"を定義しています。すると、適切なシグネチャを持つBeginInvokeメソッドとEndInvokeメソッドがこのデリゲートに自動的に定義されます。このBeginInvokeメソッドを呼び出すことにより、MyMethodメソッドの非同期呼び出しが開始されます。BeginInvokeメソッドはIAsyncResultオブジェクトを返し、すぐに制御を戻しますので、MyMethodメソッドが終了するまでブロックすることはありません。結果を取得するためには、EndInvokeメソッドを使います。EndInvokeメソッドを呼び出したときに非同期処理が完了していれば制御はすぐに戻りますが、まだ終わっていなければ終了までブロックします。非同期デリゲートを使用する際に問題となるのは、「非同期に呼び出したメソッドがいつ終わったかどうやって知るか」という点でしょう。ヘルプ「非同期プログラミングの概要」を参考にすると、その方法には次の4つが挙げられます。EndInvokeメソッドで呼び出しが終了するまでブロックする待機ハンドルを使って待機するIAsyncResult.IsCompletedプロパティがTrueになるまで待つ呼び出しが終了したときにコールバックメソッドが実行されるようにする1.の方法は一番初めのコードで説明しましたので、残りの3つの方法について説明していきます。2.待機ハンドルを使って待機するIAsyncResult.AsyncWaitHandleプロパティにより待機ハンドル(WaitHandle)を取得し、WaitHandle.WaitOneメソッドにより非同期処理が終了するまで待機させることができます。待機ハンドルに関しては、.NETプログラミング研究の第22号をご覧ください。次に簡単な例を示します。EndInvokeを呼び出す前にWaitHandle.WaitOneメソッドを呼び出しています。}}3.IAsyncResult.IsCompletedプロパティがTrueになるまで待つ非同期処理が終了するとIAsyncResult.IsCompletedプロパティがTrueになりますので、この値を確認することにより、非同期に呼び出したメソッドの終了を知ることができます。この方法は呼び出し元のスレッドを待機させませんので、非同期処理中にユーザーからの入力を受け付けたい時などに使えます。下の例ではIAsyncResult.IsCompletedプロパティがTrueになるまでループしてから、EndInvokeを呼び出しています。}}4.呼び出しが終了したときにコールバックメソッドが実行されるようにする非同期処理が終了した時にコールバックメソッドを呼び出すことができます。コールバックメソッドはAsyncCallbackデリゲートと同じシグネチャである必要があります。コールバックメソッドはスレッドプールスレッド(非同期処理が行われたスレッド)で実行されることに注意してください。次の例ではBeginInvokeメソッドを呼び出す際、コールバックメソッドの他に、呼び出しを開始するために使用したデリゲート"dlgt"を渡すことにより、コールバックメソッド内でEndInvokeメソッドを呼び出せるようにしています。