ITコンサルの日常

ITコンサル会社に勤務する普通のITエンジニアの日常です。

続々・デリゲートの非同期呼び出し

リファレンスマニュアルにこんな記述を見つけた。
AsyncResult.AsyncWaitHandle プロパティ

AsyncWaitHandle プロパティに格納されている WaitHandle を使用して、非同期の呼び出しが完了するまで現在のスレッドをブロックできます。ただし、WaitHandle は、BeginInvoke の呼び出し時に指定された AsyncCallback がある場合には、それを無視します。したがって、WaitHandle を使用して、非同期の呼び出しが完了するまでスレッドをブロックした場合でも、AsyncCallback が実行を完了する前にアプリケーションがシャットダウンしてしまう状況が生じる可能性があります。

というわけで、まさに僕が遭遇したような事象のようです。
で、色々たどった結果、非同期デリゲートを同期させるやり方が載ってました。
要は、AsyncCallback使ったら出来ませんってことですね。

非同期デリゲートのプログラミング サンプル

昨日までのサンプルをいじるとこんな感じ。

using System;
using System.Runtime.Remoting.Messaging;

class FunctionPointer
{
        public delegate int twoitem(int a, int b);

        public static int add(int a, int b)
        {
                return a + b;
        }

        static void Main(string[] args)
        {
                // 関数ポインタを定義
                FunctionPointer.twoitem fp;

                fp = FunctionPointer.add;

                // AsyncCallbackは指定しない(null)
                AsyncResult ar = (AsyncResult)fp.BeginInvoke(5, 3, null, null);

                Console.WriteLine("非同期呼び出し完了");

                while(!ar.IsCompleted)
                {
                        ar.AsyncWaitHandle.WaitOne(10000, false);
                }

                int result = fp.EndInvoke(ar);
                Console.WriteLine("result = {0}", result);
        }
}

結果はこう。

非同期呼び出し完了
result = 8

今度こそ(?)無事できました。