C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト


(過去ログ 18 を表示中)
■6849 / )  Re[2]: Control.Invokeが使えない件。
□投稿者/ れい (59回)-(2007/08/25(Sat) 02:34:12)
2007/08/25(Sat) 02:48:14 編集(投稿者)
No6846 (NyaRuRu さん) に返信
> 2007/08/24(Fri) 23:14:17 編集(投稿者)
> ■No6843 (れい さん) に返信
>>Control.InvokeやEndInvokeを何も考えずに使うと、
>>Controlを廃棄した際にデッドロックします。
>
> ほんとかなと思って試してみましたが,
> 以下のケースでは閉じたフォームに対する Invoke で InvalidOperationException 例外が発生しました.

スレッド間通信の問題ですので、一回だけでは再現しない場合もあります。
連続で何回も行ったり、高負荷時に試さなくてはいけません。
ダメな同期機構だと、開発時には大丈夫なのに、ある環境ではいつもダメ、
見たいなことがありますので、たくさん試して1回でもダメならダメです。
問題ないことの証明は激しく難しいですが。

適当な時間経ったら自動で閉じるFormをつくり、
延々とFormを作ってはInvoke、Formを作ってはInvoke、を繰り返して確認したところ…
Invokeで発生する可能性のある例外は、
・InvalidOperationException
・ObjectDisposedException
・System.ComponentModel.InvalidAsynchronousStateException(2.0のみ
でした。
また、600〜3000回に1回ほどInvokeでフリーズしました。
Invoke先で何もしないと3000回試してもフリーズしませんでした。
(最初は2回に1回くらいだったんですが、再起動したら減りました。)
環境とかで問題が発生する確率が大きく変わるので頻度は参考程度ですが、
http://bbs.wankuma.com/index.cgi?mode=al2&namber=6760 のコードでは
デッドロックが起こりえることは間違いありません。

> 別スレッドでウィンドウを開いていますよね? あれって
>略
> みたいなことをしたいということなのでしょうか?

あのスレッドではそうでしょう。
あんまりないですが、こういう仕様にしたいときもたまにあります。
Control.InvokeはGUIが無くても止まりますので、今回はあまり関係ないです。

No6847 (渋木宏明(ひどり) さん) に返信
> Control.Invoke() が最終的に SendMessage() を呼び出しているなら、存在しないウィンドウへの SendMessage() はブロックではなくエラーになるはずで、その時例外が発生するというのは(とりあえずは)納得できる実装です。

はい。おかしいときに例外は正しい。私もそれを期待します。
デッドロックは困る。

ちなみに、Control.InvokeはPostMessageを使っています。

> Control.Invoke() で立ち往生するケースがあるということですが、SDK レベルで SendMessage() を使っていても、使い方がまずければデッドロックします。
> なので、Control.Invoke() でデッドロックするのも似たような状況なんじゃないかなーと。

変な使い方をすればうまく動かないってのはなんでもそうなので、いいと思います。
Control.Invoke()でデッドロックしないコードが見当たらないのが
問題ではないかと。

Invoke先で何もしなければ今のところデッドロックは起こしませんが、
何もしなければInvokeの意味がないですし、
本当にデッドロックしないかもわかりません。
もしかしたら条件によってはロックするかも知れません。

どういうInvoke内容だったら安全なんでしょうか?
MSDNをいくら読んでも、どこを探しても、明確な指針が見当たりません。
それで皆さんの意見を聞きたかったのです。

話の内容からすると、
Nyaruruさんも渋木宏明(ひどり)さんも、
Control.Invokeのデッドロックに遭遇したことがないようですね。

以前問題を見つけたときはほぼ毎回デッドロックしてたんですが、
今調べてみると、たまにしか止まらなくって検証が大変です。
はてさて、どうしたものか。
返信 編集キー/


管理者用

- Child Tree -