C# 入門 & 実践 / C sharp
4-29. イベント - 3 - 非同期で実行&コールバックで返り値を取る!
MyHandlerの呼び出しを一つずつ順番に非同期 ( BeginInvoke ) で呼び出す。
Callbackメソッドを設定し返り値を取るよう設定!( EndInvoke )
出力は Hello Goodbye ともに60のときのみ
// イベント情報
class BbEventArgs : EventArgs
{
private readonly int cnt = 0;
public BbEventArgs( int cnt )
{
this.cnt = cnt;
}
public int Cnt
{
get { return cnt; }
}
}
// メインで動くクラス。
class BbEvent
{
private int mycnt = 0;
// 独自のイベント情報を利用するためのハンドラー
// 返り値 int を設定。
public delegate int BbHandler(object o, BbEventArgs e);
// イベントハンドラーのデリゲート宣言です。。。
public event BbHandler MyHandler;
// イベントを発生させるためのメソッド。
protected virtual void OnMyHandler( BbEventArgs e )
{
if (MyHandler != null)
{
// 今までは一回で処理していた。
// MyHandler(this, e);
// 非同期で処理させる。
foreach (BbHandler del in MyHandler.GetInvocationList() )
{
Console.WriteLine("メソッド開始! : {0} ", del.Method.ToString());
del.BeginInvoke(this, e, new AsyncCallback(ResultsBack), del);
}
}
}
// コールバック用メソッド
// デリゲートメソッドが終了したら呼ばれる!
private void ResultsBack(IAsyncResult iar)
{
// BbHandlerにキャスト
BbHandler bh = (BbHandler)iar.AsyncState;
// 返り値を見る。
int result = bh.EndInvoke(iar);
Console.WriteLine("メソッド終了 : {0} : ret : {1}", bh.Method.ToString() ,result);
}
// このメソッド内でイベント呼び出しがあります。
public void Run()
{
int i = 1;
for (;;)
{
mycnt++;
// 10 ミリ秒休憩
Thread.Sleep( 10 );
// 30 で割り切れるときにイベント発生
if ((i % 30) == 0)
{
// イベントオブジェクト生成
BbEventArgs be = new BbEventArgs(i);
// イベントを発生させる!
OnMyHandler(be);
}
i++;
if (i > 100)
{
i = 1;
}
if (mycnt > 100)
{
Console.WriteLine("終了");
// 300 ループして終わる
return;
}
}
}
}
// イベント発生時の動作 1
class BbHello
{
private int mycnt = 0;
// Subscribe :メソッドを設定
public void setMethod(BbEvent e)
{
e.MyHandler += new BbEvent.BbHandler(SayHello);
}
//
public int SayHello(Object o, BbEventArgs e)
{
// 10 ミリ秒待ちます!
Thread.Sleep(10);
mycnt++;
if (e.Cnt == 60)
{
Console.WriteLine("SayHello : mycnt = {1} / イベント情報 cnt = {0}", e.Cnt, mycnt);
return 1;
}
else
{
// 出力しない場合 0 を返す
return 0;
}
}
}
// イベント発生時の動作 1
class BbGoodbye
{
private int mycnt = 0;
// Subscribe :メソッドを設定
public void setMethod(BbEvent e)
{
// e.MyHandler += new BbEvent.BbHandler(SayGoodbye);
e.MyHandler += delegate(Object o, BbEventArgs ev)
{
mycnt++;
if (ev.Cnt == 60)
{
Console.WriteLine("SayGoodbye : mycnt = {1} / イベント情報 cnt = {0}", ev.Cnt, mycnt);
return 1;
}
else
{
// 出力しない場合 0 を返す
return 0;
}
};
}
}
class MyTester
{
static void Main()
{
// メイン:イベント発行を行うクラス
BbEvent be = new BbEvent();
// イベント発行時の実行メソッド
BbHello bh = new BbHello();
BbGoodbye bg = new BbGoodbye();
// subscribe : 実行メソッドをセットする
bh.setMethod(be);
bg.setMethod(be);
// Run を実行!
be.Run();
}
}
非同期で開始
SayHelloの後にSayGoodbyeを設定したので、その順番どおりに開始&終了している。
非同期であることはわかり難い^-^;
返り値はちゃんと取れていますね。
メソッド開始! : Int32 SayHello(System.Object, HelloWorld.BbEventArgs)
メソッド開始! : Int32
b__0(System.Object, HelloWorld.BbEventArgs)
メソッド終了 : Int32 SayHello(System.Object, HelloWorld.BbEventArgs) : ret : 0
メソッド終了 : Int32 b__0(System.Object, HelloWorld.BbEventArgs) : ret : 0
メソッド開始! : Int32 SayHello(System.Object, HelloWorld.BbEventArgs)
メソッド開始! : Int32 b__0(System.Object, HelloWorld.BbEventArgs)
SayHello : mycnt = 2 / イベント情報 cnt = 60
メソッド終了 : Int32 SayHello(System.Object, HelloWorld.BbEventArgs) : ret : 1
SayGoodbye : mycnt = 2 / イベント情報 cnt = 60
メソッド終了 : Int32 b__0(System.Object, HelloWorld.BbEventArgs) : ret : 1
メソッド開始! : Int32 SayHello(System.Object, HelloWorld.BbEventArgs)
メソッド開始! : Int32 b__0(System.Object, HelloWorld.BbEventArgs)
メソッド終了 : Int32 SayHello(System.Object, HelloWorld.BbEventArgs) : ret : 0
メソッド終了 : Int32 b__0(System.Object, HelloWorld.BbEventArgs) : ret : 0
終了
ここでSayHelloメソッド内にSleep( 10 )を入れてみる。
メソッド開始! : Int32 SayHello(System.Object, HelloWorld.BbEventArgs)
メソッド開始! : Int32 b__0(System.Object, HelloWorld.BbEventArgs)
メソッド終了 : Int32 b__0(System.Object, HelloWorld.BbEventArgs) : ret : 0
メソッド終了 : Int32 SayHello(System.Object, HelloWorld.BbEventArgs) : ret : 0
メソッド開始! : Int32 SayHello(System.Object, HelloWorld.BbEventArgs)
メソッド開始! : Int32 b__0(System.Object, HelloWorld.BbEventArgs)
SayGoodbye : mycnt = 2 / イベント情報 cnt = 60
メソッド終了 : Int32 b__0(System.Object, HelloWorld.BbEventArgs) : ret : 1
SayHello : mycnt = 2 / イベント情報 cnt = 60
メソッド終了 : Int32 SayHello(System.Object, HelloWorld.BbEventArgs) : ret : 1
メソッド開始! : Int32 SayHello(System.Object, HelloWorld.BbEventArgs)
メソッド開始! : Int32 b__0(System.Object, HelloWorld.BbEventArgs)
メソッド終了 : Int32 b__0(System.Object, HelloWorld.BbEventArgs) : ret : 0
メソッド終了 : Int32 SayHello(System.Object, HelloWorld.BbEventArgs) : ret : 0
終了
予定通りSayHelloが先に呼ばれているのに終了は遅くなっていますね!^-^。
4-28. イベント - 2 - 独自のイベントデータを使用する « 4. C# 入門 Level 2
C# 入門 & 実践 / C sharp