これは今朝成功しなかった質問のバージョンをポーズする新しい試みです。ダイナミックな呼び出しで解き放たれたスタックを含むパズル
は、私たちが直接
namespace ConsoleApplication3
{
delegate void myFoo(int i, string s);
class Program
{
static void Main(string[] args)
{
Foo(1, "hello");
Delegate Food = (myFoo)Foo;
Food.DynamicInvoke(new object[] { 2, null });
}
static void Foo(int i, string s)
{
Console.WriteLine("If the next line triggers an exception, the stack will be unwound up to the .Invoke");
Console.WriteLine("i=" + i + ", s.Length = " + s.Length);
}
}
}
VSを実行している間はFooで例外がトリガすると、デバッガが示してダブルクリックし、実行して、Visual Studio 2010の内部で一度実行して、もう一度よ次のプログラムを考えてみましょうFooの2番目のWriteLineに問題が発生したことを示しています。
しかし、実行ファイルを直接実行しているときに例外が発生すると、プログラムが処理されなかった例外をスローしたことを示す小さなポップアップウィンドウがCLRから取得されます。デバッグをクリックし、VSデバッガを選択します。この場合、スタックは最新の.DynamicInvokeのポイントまで巻き戻され、デバッガでアタッチすると、例外時に存在していたスタックコンテキストが部分的に失われます。
例外イベントの「内部例外」部分内には、限定された形式で存在します。関連情報をクリックして展開し、問題が発生した行番号を見つけます。しかし明らかにローカル変数やその他のコンテキストはなくなります。
.DynamicInvoke(たとえば、Mainの1行目でFoo(1、null)を呼び出す)を使わずに同じことを試みても、.exeファイルをダブルクリックしても正しい行番号を取得しますデバッガが接続するとき。同様に、.exeをクリックしてアプリケーションを起動すると、例外がスローされる前にデバッガがアタッチされます。
どのように動的リフレクション/呼び出しを使用するアプリケーションがこの問題を回避できるか知っていますか?私の意図するユースケースでは、ここでは言及しない名前のシステムでは、.DynamicInvokeで使用されるオブジェクトの型シグネチャ、または採用される引数の数を予測できません。静的な型付けやジェネリックスは、これの方法ではありません。
私の質問は、例外がスローされた後にプログラムにアタッチするときと比べて、デバッガから直接実行するときに、なぜそのような異なる動作を得るのか誰にも分かりますか?
デバッガでプログラムを実行している最初のシナリオでは、デバッガで「最初のチャンス」または「2番目のチャンス」例外を解除するように設定していますか?つまり、例外が*スローされたときにブレークするようにデバッガを設定することができます* - 最初のチャンス - または例外*がランタイムによってcatchブロック*で処理されなかったときに中断する* 2回目のチャンス。デバッガの動作は、これらの2つのシナリオでは異なる場合があり、見ている違いを説明する*かもしれません。 (私はあなたの問題を再現しようと実際に試みたことはありません;これはちょうど教育的な推測です) –
"Debug/Exceptions ..."ウィンドウの "Thrown"列のチェックボックスを見てください。チェックされたものはあなたに「最初のチャンス」の行動を与えます。 – kvb
@kvp:ありがとう。これを試しましたが効果がありません。私は、悪い行為がで起こっていると推測している。exeはCLRから直接実行され、デバッガのパラメータによって制御されません(たとえば、VSがスタックを参照するまでに、すでに解放されています)。私の理論は、私がVSの下で走ったときに、VSが最初のチャンスの行動を最初に得ているということです。私が.exeの下で走った場合、そのチャンスを得られません。したがって、後者の場合、.Invokeは傍受してから再スローされます例外がInvoke行に表示され、実際にそれをトリガーしたものではない理由を説明します。推測する。 –