2

InvokeUI 状態の更新に使用するソケット処理スレッドで実行されるイベント ハンドラーがあります。

コール スタックのさらに上のどこかにランナウェイがあり、FormatExceptionそれをキャッチして分析しようとしていますが、UI スレッドでデバッガーを中断させることができないことがわかりました — 呼び出しまで例外がバブルしているようです私が何をしてもスレッド。

Private Delegate Sub newDataDelegate(ByVal data As String)
Private Sub onNewData(ByVal data As String) Handles _server.clientHasData
   If Me.InvokeRequired Then
      Me.Invoke(New newDataDelegate(AddressOf onNewData), data)
      Exit Sub
   End If

   Try
      updateGuiWith(data)
   Catch ex As FormatException
      System.Diagnostics.Debugger.Break()
   End Try
End Sub

スタック トレース:

at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
at <X>.MainForm.onNewData(String data)
   in <X>.vb:line 377
at <X>.Server.onProbeData(String data)
   in <X>:line 104

( <X>= 編集済み)

その結果、デバッガーは (onNewDataソケット スレッドで呼び出されたコードで) 呼び出しスタックを下に分割し、呼び出しサイトでスタック トレースが終了します。例外の原因がわかりません。(さらに悪いことに、呼び出しはほとんどの場合同じ引数に対して機能するため、デバッガーの助けなしに予測して追跡することはできません。)

分離されたテストケースをさらに抽出する前に、デリゲート駆動の呼び出しの背後で発生した例外に対して、これは予想される動作ですか?

4

3 に答える 3

1

デリゲート駆動の呼び出しの背後で発生した例外に対して、これは予想される動作ですか?

いいえ、それはデリゲートの Begin/Invoke() メソッドを実際に使用していないためです。Control.Invoke() を使用しています。これは、単にデリゲートを引数として取る Control クラスのメソッドです。デリゲートの Begin/Invoke メソッドとは動作が大きく異なります。命名の選択は少し残念でした。主な違いは次のとおりです。

  • BeginInvoke を呼び出すときに EndInvoke を呼び出す必要はありません。
  • Invoke 呼び出しは例外をマーシャリングしますが、BeginInvoke 呼び出しはマーシャリングしません。
  • Invoke のためにマーシャリングされた例外は、最も内側の InnerException です。事故の原因となった例外のみが表示されます。別の例外によってキャッチされて再発生し、その InnerException メンバーで元の例外が渡された場合、それらの例外はまったく表示されません。

はい、これにより、スタック トレースを見ると、ポイント A からポイント B に移動した方法を理解するのが非常に難しくなる可能性があります。非常に残念な動作です。設計の選択は明らかではありません。呼び出されたコードで例外をキャッチして処理する以外に、簡単な回避策はありません。

または、BeginInvoke を支持するには、一般に、UI 更新の遅延によってスレッドが行き詰まらないようにするために使用するメソッドです。完全なスタック トレース診断を使用して、UI スレッドで例外が発生します。

于 2012-11-26T16:01:34.600 に答える
0

に置き換えるCatch ex As FormatExceptionCatch ex As Exception、探していた呼び出されたスレッドのブレークが得られ、問題の実際の例外はInvalidCastException. 内部例外は ですFormatException。これが、キャッチされなかった理由です。

.NET の例外に関する私の理解はまだかなり初歩的です (何よりもまず C++ 開発者であるため)。そのため、さまざまなレベルの例外ラッパーのこの概念はかなり異質です。しかし、最終的には、このメカニズムは Hans が回答で説明したとおりです。

長期的にBeginInvokeは、意志に切り替えると、この頭痛を完全に回避できるようです. ただし、今のところ、スタック トレースがあり、実際の問題を解決できます。

質問に対する答えは、デリゲート主導の「Control.Invoke」呼び出しの背後で例外を処理できますか? はい。_

于 2012-11-26T16:37:41.290 に答える
0

これを読んだことから、

http://charlieflowers.wordpress.com/2005/04/26/controlinvoke-and-exception-propogation-short-form/

はい、これは例外をバブルアップするためのものだと言います。記事を正しく理解していれば、例外は飲み込まれ、例外情報が Invoke 関数に返され、そこで再スローされます。ただし、BeginInvoke非同期呼び出しを使用する場合、例外は呼び出しによってバブルアップされませんBeginInvoke

私は VS Express を使用していませんが、通常は [Debug] > [Exceptions] の下で、[Common Language Runtime Exceptions] の横にある [Thrown] ボックスをオンにします。次に、デバッガーは最初の例外が発生した場所で停止する必要があります。

これはおそらく当てはまりSystem.Diagnostics.DebuggerStepThroughませんが、デバッガーが例外をスローするコードをスキップする原因となるような属性について、コードをチェックできます。

于 2012-11-26T15:25:20.740 に答える