2013-10-09 26 views
1

該類存在於它自己的DLL中。調用防爆方法相當明顯導致異常被拋出和處理:AppDomain.FirstChanceException事件訂閱導致FatalExecutionEngineError

class Foo : MarshalByRefObject 
{ 
    public void Ex() 
    { 
     object o = null; 

     try 
     { 
      string s = o.ToString(); 
     } 
     catch { } 
    } 
} 

以下負載包含富到另一個AppDomain中的DLL,創建一個Foo和調用防爆方法。

using System; 
using System.Diagnostics; 
using System.Runtime.ExceptionServices; 
using RemoteCode; 

namespace AppDomainTraceTest 
{ 
    class Program 
    { 
     static void Main() 
     { 
      AppDomain appDomain = AppDomain.CreateDomain("TEST", 
       null, 
       new AppDomainSetup 
       { 
        ApplicationBase = AppDomain.CurrentDomain.BaseDirectory 
       }); 

      // appDomain.FirstChanceException += 
      //  (s, e) => Debug.WriteLine("* " + e.Exception.Message); 

      Bar bar = new Bar(); 
      bar.Subscribe(appDomain); 

      Foo foo = (Foo)appDomain.CreateInstance("RemoteCode", "RemoteCode.Foo").Unwrap(); 
      foo.Ex(); 
     } 
    } 

    public class Bar : MarshalByRefObject 
    { 
     public void Subscribe(AppDomain ad) 
     { 
      ad.FirstChanceException += OnFirstChanceException; 
     } 

     private void OnFirstChanceException(object sender, FirstChanceExceptionEventArgs e) 
     { 
      Debug.WriteLine("* " + e.Exception.Message); 
     } 
    } 
} 

結果是FatalExecutionEngineError:

The runtime has encountered a fatal error. The address of the error was at 0x62c6529d, on thread 0x26f0. The error code is 0x80131506. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.

它發生在這條線中的Foo:

string s = o.ToString(); 

如果我註釋掉線,包括酒吧,並取消前面的行然後代碼工作正常,並將異常消息寫入調試控制檯:

appDomain.FirstChanceException += 
    (s, e) => Debug.WriteLine("* " + e.Exception.Message); 

//Bar bar = new Bar(); 
//bar.Subscribe(appDomain); 

Foo foo = (Foo)appDomain.CreateInstance("RemoteCode", "RemoteCode.Foo").Unwrap(); 
foo.Ex(); 

我在做一些愚蠢的事,還是這是一個錯誤?

回答

1

在這樣的情況下,標籤「bug」非常合適,不應該存在來自普通託管代碼的FEEE。然而,您正在給CLR一個非常困難的時間,在非常關鍵的時間將事件處理函數從一個AppDomain調用到另一個AppDomain。很明顯,它沒有裝備來解決這個問題。

您需要強烈考慮避免這種情況。只要您將事件處理程序保留在同一個AppDomain中,它就可以正常工作。這工作正常,例如:

public class Foo : MarshalByRefObject { 
    public Foo() { 
     AppDomain.CurrentDomain.FirstChanceException += (s, e) => { 
      Debug.WriteLine("* " + e.Exception.Message); 
     }; 
    } 
    // etc... 
} 

可能不方便記錄我想象。您可以在connect.microsoft.com上提交此錯誤的反饋報告。

+0

謝謝。我向微軟提交了一個bug(連接804982) –