C# と VB.NET の質問掲示板
ASP.NET、C++/CLI、Java 何でもどうぞ
C# と VB.NET の入門サイト
(過去ログ 18 を表示中)
掲示板トップ
C# と VB.NET のサンプル
新規作成
利用方法/規約
トピック表示
ランキング
記事検索
過去ログ
■6843
/ )
Control.Invokeが使えない件。
□投稿者/ れい
(58回)-(2007/08/24(Fri) 19:16:28)
分類:[.NET 全般]
こちら(
http://bbs.wankuma.com/index.cgi?mode=al2&namber=6760
)で話してたんですが、
皆さんの意見を聞きたいので、タイトルと内容を合わせてスレッド立てます。
タイトルの通り、「Control.Invokeが使えない」件に関して、
私の事実誤認であるとか、同意であるとか、皆さんの意見をください。
Control.InvokeやEndInvokeを何も考えずに使うと、
Controlを廃棄した際にデッドロックします。
Invokeがウィンドウメッセージを送り、返事を待ってる間に
Controlが廃棄された場合、いつまで待っても返事が返ってこないからです。
これは
http://osdir.com/ml/windows.devel.dotnet.clr/2004-04/msg00157.html
http://www.microsoft.com/japan/msdn/community/gdn/ShowPost-26227.htm
などなど、かなり既出の件です。
この対策をいろいろ考えたのですが、
Control.Invokeを安全に使える方法が全く存在せず、
Invokeを使うこと自体が間違いであるという結論に至ってしまいました。
ControlやFormはいつ廃棄されるのか、
Invokeする側(Invoker)からはわかりません。
Invokeされる側(Invokee)でフラグを立てて回避しようとしても、
Invokeメソッド内で実際にウィンドウメッセージを送るまでの間に
ControlやFormが死んでしまうとデッドロックします。
WorkerThreadをInvokerとする場合も同様で、
WorkerThreadが死ぬ前にControlが死ぬ可能性のある場合は、
WorkerThreadがInvokeでデッドロックし、残ってしまいます。
Controlは、WM_DESTROYやWM_QUITで、いつでも死ぬ可能性があり、
Controlが死ぬ前にWorkerThreadが死ぬのを保証するには、Abortし終了を待つしかありませんが、
その間にInvokeされてる場合もありうるのでダメです。
いろいろ考えましたが、どうやってもControl.Invokeを安全には使えませんでした。
代替方法はBeginInvokeを投げっぱなしにするか、EndInvokeをタイムアウト付きで呼ぶことでした。
ですが、
http://msdn2.microsoft.com/ja-jp/library/757y83z4
(VS.80).aspx
http://www.atmarkit.co.jp/fdotnet/dotnettips/312ctrlinvoke/ctrlinvoke.html
http://codezine.jp/a/article.aspx?aid=139#invoke
http://dobon.net/vb/dotnet/programing/progressdialog.html
などなど、
ネット上にも、MSDNにもInvokeを使ったサンプルはたくさんあります。
見る限りどれもデッドロックを引き起こすコードで、
いくつかは検証してみましたが、実際にデッドロックを引き起こしました。
MSDNのサンプルでさえ、Formを閉じたときにスレッドがWaitのまま残りました。
私が検証した限りでは、安全に使うことはできませんでしたし、
理論上できないのではないかと私は思っています。
もし安全に呼ぶ方法が一つでもあるなら存在意義がありますが、
一つも無いなら、ただ邪魔なだけのメソッドです。
だれか発言力のある偉い人が、「Control.Invokeはダメ」って言ってくれれば安心するんですが、
見当たりません。
私一人が思ってるだけ、言ってるだけでは、自分自身も説得できなくて。
誰か偉い人、「ダメ」って言ってくれませんか?
また、「きちんと使えてる。お前のチエが猫並みなだけ」って人がいるなら、
是非猫にチエをご教授ください。
返信
編集キー/
編集
管理者用
-
Child Tree
-