- - PR -
TreeViewのDragDropでの例外について
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2006-10-30 15:03
こんにちは。
TreeViewのDragDropについての質問です。 DragDrop内で発生した例外は MyApplication_UnhandledExceptionでひろうことはできないのでしょうか? DragDrop内で意図的に0割を行ってもDragDrop内のエラー発生箇所以降の 処理は行われませんが、次のイベントの処理に移ってしまいます。 環境は VB.NET 2005 Windowsアプリケーション わかりにくい説明で申し訳ありませんがよろしくお願いします。 | ||||||||
|
投稿日時: 2006-10-30 16:40
無理だと思います。
Try ~ Catch であれば、例外を補足することはできます。 ところで、なぜ UnhandledException として例外をキャッチしたいのでしょうか? _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||
|
投稿日時: 2006-10-30 17:06
じゃんぬねっとさん、返信ありがとうございます。
try〜catchで確かに例外は補足できるのですが、 理想的な処理としては、catchした箇所ではロールバックのみを行い その後、例外をthrowしたいと思っています。 例外をthrowする理由は、ここで発生する例外の原因は バグやDBアクセス時に何か致命的なエラーが発生した場合と 考えられるのでアプリを終了させたいと思っています。 DragDrop以外の箇所はこの方法でうまくいっているので 統一したいということで質問しました。 ただ、無理ということだと別の方法を考えないといけませんね。。。 | ||||||||
|
投稿日時: 2006-10-30 17:40
ドラッグ&ドロップはスレッドを跨ぎますからね。
別スレッドで発生した例外はメインスレッドには通知されません。 そこでキャッチした例外を変数に格納しておいて、 終了後にその変数が null かどうかで判断する方法がとられることが多いです。 別スレッド、非同期デリゲート、例外あたりで検索してみると結構ヒットします。 というか、例外は発生させてはいけないのが前提で、 DragEffect を使ってドロップさせないように制御するのが王道です。 | ||||||||
|
投稿日時: 2006-10-30 19:16
masaさん、返信ありがとうございます。
ドラッグ&ドロップはスレッドが違うということですね。。。 たしかにそれでは、例外は通知されませんね。 非同期デリゲートで調べてみたのですが、 いまいちよくわかりません。 メインスレッドからスレッドを作成してという基本的な動きは わかるのですが、TreeViewのDragDropでどう応用させればいいか わかりません。 もう少しヒントをいただけないでしょうか? 例外を発生させないのが前提というのはよくわかりますが 先ほども記述したようにバグ等で例外が発生した場合のことを 考えてこのような処理方法を考えています。 | ||||||||
|
投稿日時: 2006-10-31 09:11
ドラッグ&トドロップ処理の内部で別スレッドが作成されていますから、
あえてプログラムコードでスレッドを沸けたりする必要はないと思います。 DragDrop とか DragOver などのイベントの処理の中で 例外が発生しそうな部分をTry Catch で囲みます。 そしてキャッチした例外を変数にセットしておけば発生したかどうかわかります。 下の例のようにすれば発生した時点で何かをさせることも可能です。 どんな処理なのかがわかりませんから目的に沿っているかどうかはわかりませんが、 参考にしてみてください。 private void textBox1_DragDrop( object sender, System.Windows.Forms.DragEventArgs e) { try { // 例外を発生させてみる int i = 0; i = 1 / i; } catch ( Exception ex ) { // 発生した例外を退避 this.ExceptionInDragDrop = ex; } } // ドラッグ&ドロップ中に発生した例外 private Exception ExceptionInDragDrop { get { return m_ExceptionInDragDrop; } set { if ( m_ExceptionInDragDrop == value ) { return; } m_ExceptionInDragDrop = value; OnExceptionInDragDropChanged(); } } private Exception m_ExceptionInDragDrop; // ExceptionInDragDrop が変更されたときの処理(少し手抜き) private void OnExceptionInDragDropChanged() { System.Diagnostics.Debug.WriteLine( "例外発生:" + this.ExceptionInDragDrop.ToString() ); } ※ VB.NET って書いてあるのに後で気づきました。 少し書式は違いますが伝わりますよね? | ||||||||
|
投稿日時: 2006-10-31 09:55
masaさん、丁寧な解説ありがとうございます。
ですが、申し訳ないのですがもう一点質問です。 別スレッド内で発生した例外を別スレッドで処理をしている間は メインスレッドでは感知できませんよね? できれば、コーティング例でいうとm_ExceptionInDragDropに 例外が設定されていたらメインスレッドで例外をthrowすると いうような処理にしたいのですが。。。 ここでよくわからないのがメインスレッドで例外をthrowする という処理をどこのメソッドで記述すればいいかということです。 何度も何度も申し訳ありませんがよろしくお願いします。 | ||||||||
|
投稿日時: 2006-10-31 10:21
残念ながらドラッグドロップ中にスローさせても握りつぶされます。
例外が発生したときには呼び出し元へ通知されますが、 ドラッグドロップに呼び出し元はありませんよね? private void OnExceptionInDragDropChanged() { // 例外をスローしても通知はされない throw this.ExceptionInDragDrop; } ロールバックなどは例外をキャッチしたときに処理をするしかないでしょうね。 スローした例外をどこかでキャッチしたとしてそこにロールバック処理を記述するのと、 この例でいう OnExceptionInDragDropChanged にロールバック処理を記述するのとで違いはないように思います。 あえてスローさせる意味はないように思いますが、どのような理由でしょう。 <追記> 「コントロール・フォームが存在しているスレッド」をメインスレッドとするなら、 コントロール・フォームの InvokeRequired プロパティを調べることによって 現在のコードがメイン・サブスレッドのどちらで実行されているかがわかります。 ドラッグドロップの場合は内部でスレッド切り替えが行われていますので、 DragDrop イベントに記述した処理自体はメインスレッドで行われています。 しかし、呼び出し元が別スレッドにあるため、発生した例外は握りつぶされます。 握りつぶされる前に自分でキャッチして変数に格納しておくなり、 キャッチと同時に必要な処理を行ったりする必要があります。 [ メッセージ編集済み 編集者: masa 編集日時 2006-10-31 10:26 ] |