- - PR -
「InvokeRequired=True」と「デバッグなしで開始」と「デバッグ開始」
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-12-11 18:26
ご無沙汰しております。
外部へ開発委託したプログラムの検収作業をしているのですが、 納品されたコードをなんとなく眺めていたら、 ThreadPoolを使って、比較的長い処理を行っているところで、 フォームに貼り付けられたラベルコントロールへの操作をしているコードを見つけました。 IDE上で、デバッグをしてみたところ、案の定、InvokeRequiredがTureとなっており、 ラベルコントロールへの操作のところで例外がスローされました。 当然の動きなのですが、いままで、検収作業をIDE上のデバッグではなくて、 ビルドされたアセンブリを直接実行して行っていました。 そのときは例外がスローされずに問題なく動いているように見えました。 ハテ?と思い、今度はIDE上で、「デバッグなしで実行」をしてみたところ、 直接実行のときと同様、例外がスローされませんでした。 以上の動作で、「デバッグ開始」で、例外がスローされるのは、正しい動作だと思うので、 当然、InvokeRequiredがTrueとなることを考慮したコードに修正が必要と考えますが、 その前に、なぜ、「デバッグなしで開始」や、アセンブリを直接実行したときは、 例外がスローされないのか理由を知りたいのです。 どなたがご存じの方、コメントをいただけないでしょうか。 Visual Studio 2005 C# 2005 | ||||||||||||
|
投稿日時: 2008-12-11 18:44
(利用規約違反のため削除いたしました。@ITクラブメンバーシップセンター)
| ||||||||||||
|
投稿日時: 2008-12-12 05:38
#if で非デバッグ時は UnhandledException や ThreadException で例外を握りつぶすようになっていたりして。 つか、そもそも直接実行時に、そのラベルは期待通りに表示更新されているのでしょうか? 実装面での問題が、機能面でも影響を及ぼしているような気がします。 | ||||||||||||
|
投稿日時: 2008-12-12 07:39
バグが発見されやすいようにデバッグ時は例外になるように動作が変更されましたが、デバッガにアタッチしてない状態では、過去との互換性のために例外にはしないようになってたはずです。
※.NET Framework の Ver.1.1→2.0での動作変更の話です。 | ||||||||||||
|
投稿日時: 2008-12-12 10:43
おはようございます。
コメントありがとうございます。
そうなのですか、知りませんでした。 http://msdn.microsoft.com/ja-jp/library/ms171728(VS.80).aspx こちらで確認することができました。 ところで、 コントロールはスレッドセーフではない。 ↓ だから、他スレッドからの操作はエラーになる。 はわかります。ただし、それは、デバッガで実行させているときだけであって、 デバッガにアタッチしていない場合は、エラーになりません。 それは、互換性のためにそうしています。 ということであれば、じゃそもそもコントロールへのスレッドセーフなアクセスってなんなんでしょうか? 互換性を維持するために、抑止される程度のエラーということであれば、 コントロールがスレッドセーフでないということは、無視してもいいくらい 些細なことと考えていいのでしょうか? また、コントロールに対してスレッドセーフでない操作をすることによって 結局、何がどうなる可能性が考えられるのでしょうか? # 余談ですが、こんなプロパティもあるのですね。 # Control.CheckForIllegalCrossThreadCalls | ||||||||||||
|
投稿日時: 2008-12-12 14:19
こんにちは。
スレッドセーフでないということは、タイミングが悪ければ(深刻な)問題を引き起こす可能性があるということ。 じゃあ、どうすればスレッドセーフなコードが書けるか? 書籍でも購入してマルチスレッドプログラミングの勉強をしましょう。
(なんか以前にも同じようなことを書いた気がしますが・・・) もともと、ネイティブなWindows標準コントロールの操作のほとんどはWindowsメッセージを経由していますので、 マネージコードがラップしているネイティブな部分にアクセスする分に関しては、他スレッドからであっても問題はないはずです。 (たとえばLabel.Textプロパティのセットは、SetWindowText→WM_SETTEXTメッセージによってコントロールの所属するスレッドで受け取られ処理される) ただ、マネージ部分(.NETクラスライブラリ部分)は問題になる可能性があります。 たとえば(未検証ですが) Label.Textプロパティへのセットによって引き起こされるTextChangedイベントはマネージコードによって発射されているため、 呼び出した他スレッドにて実行されてしまうでしょう。 些細なことかどうかは分かりません。 問題なく動作するかもしれませんし、重大なエラーを引き起こすかもしれません。
例えば、 ご自身で作ったプログラムコードを実行中に、ある変数(スタック変数ではない)の内容が 別のスレッドによって、突然書き換えられてしまいました。 さてどうなるでしょう? ほとんど予測不可能ではないでしょうか。 | ||||||||||||
|
投稿日時: 2008-12-12 15:15
Tdnr_Symさん
こんにちは。 私の文章では、うまく伝えることができなかったようですね。 失礼しました。日本語は難しいですね。 私は、具体的なコードの書き方を尋ねているのではありません。 とどのつまり、そんな深刻な障害を引き起こす可能性があるのなら、 互換性のためというだけで、例外を抑止しする仕組みがあるのは おかしいと思ったのです。 だから他の理由があるのではないかと考え、 見識のある方の意見を伺いたかったのです。 そんなことをMSに聞けと言わそうですが・・・。 | ||||||||||||
|
投稿日時: 2008-12-12 15:50
こんにちは。
こちらこそ失礼しました。 からあげさんがもう少し開発者よりの方かと思い、 開発者に対する回答をしてしまいました。 ところで@ITにちょうど良い記事がありますね。(開発者向けですが) 複数のスレッドに対して安全な「スレッドセーフ」
スレッドセーフでないということは結局、複数のスレッドからの利用を想定していないので、 具体的にどうなるかと聞かれても答えにくいです。
MSの開発者に聞かない本当のところわからないですが、 VS2005以前のコードが動かなくなるほうが、問題だと判断したのではないでしょうか? スレッドセーフでないということは、障害を引き起こすかもしれないということで、 必ず障害を引き起こすということではありませんから。 |