BeginInvoke/EndInvoke についてメモ
以前から、かぶだいくんで、楽天RSSをリモートコンピューターで動かして、それを .NET Remoting で受信しているが、最近なぜか動かなくなってしまった。
受信イベントで画面を描画するときに、受信スレッドはUIスレッドではないため、その橋渡しとして、
IAsyncResult ar = this.BeginInvoke(new TimedEventHandler(formInvoker_InvokerHandler), new object[] { this, logicTimeManager.NowTime, new TimedEventArgs(e) }); this.EndInvoke(ar);
と書いていたのだが、
System.ObjectDisposedException はユーザー コードによってハンドルされませんでした。 Message="破棄されたオブジェクトにアクセスできません。\r\nオブジェクト名 'MainForm' です。" Source="System.Windows.Forms" ObjectName="MainForm" StackTrace: 場所 System.Windows.Forms.Control.EndInvoke(IAsyncResult asyncResult) 場所 Kabudai.TimeManager.InvokeAsync(Delegate argMethod, EventArgs argEventArgs) 場所 C:\Projects\Kabudai\Tools\TimeManager.cs:行 392 場所 Kabudai.MainForm.rakutenRssDriver_RssHandler(Object sender, DateTime eventTime, Boolean remoting, Boolean hot, RssEventArgs e) 場所 C:\Projects\Kabudai\MainForm.cs:行 3244 場所 Kabudai.RakutenRssAbstractDriver.UpdateAndNotify(DateTime nowTime, Boolean remoting, Boolean hot, Boolean committed) 場所 C:\Projects\Kabudai\RakutenRss\RakutenRssAbstractDriver.cs:行 149 場所 Kabudai.RakutenRssAbstractDriver.UpdateLine(DateTime nowTime, Boolean remoting, Boolean hot, CodeMarket codeMarket, String key, String val) 場所 C:\Projects\Kabudai\RakutenRss\RakutenRssAbstractDriver.cs:行 180 場所 Kabudai.RakutenRssAbstractDriver.EnqueLine(DateTime nowTime, Boolean remoting, Boolean hot, RakutenRssLine line) 場所 C:\Projects\Kabudai\RakutenRss\RakutenRssAbstractDriver.cs:行 197 場所 Kabudai.RakutenRssRemotingDriver.CallbackSink_OnHostToClient(CommsInfo info) 場所 C:\Projects\Kabudai\RakutenRss\RakutenRssRemotingDriver.cs:行 134 場所 RemotingServer.CallbackSink.HandleToClient(CommsInfo info) 場所 C:\Projects\RemotingServer\ServerClient\ServerTalk.cs:行 156 場所 System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object& outArgs) 場所 System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(RuntimeMethodHandle md, Object args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object& outArgs) 場所 System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg, Int32 methodPtr, Boolean fExecuteInContext) InnerException:
というエラーになってしまう。
原因を探ってみると、どうも BeginInvoke して EndInvoke で待っているときに、再入してきて再び BeginInvoke をするとこのエラーになるようだ。
アローヘッド対応のためについでにマーケットスピードのリアルフィードをオンにして、イベントの発生頻度が高くなったから目立つようになっただけで、昔から自分のアプリケーションプログラム内で持っていたバグなのかな?
単純に lock して、
lock (this) { IAsyncResult ar = this.BeginInvoke(new TimedEventHandler(formInvoker_InvokerHandler), new object[] { this, logicTimeManager.NowTime, new TimedEventArgs(e) }); this.EndInvoke(ar); }
とするとうまく動いているみたいだ。