此类存在于其自己的DLL中。显然,调用Ex方法会导致异常被抛出并处理:
class Foo : MarshalByRefObject
{
public void Ex()
{
object o = null;
try
{
string s = o.ToString();
}
catch { }
}
}
以下将包含Foo的DLL加载到另一个AppDomain中,创建一个Foo并调用Ex方法。
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:
运行时遇到了致命错误。错误的地址是0x62c6529d,位于线程0x26f0上。错误代码是0x80131506。此错误可能是CLR中的错误,也可能是用户代码的不安全或不可验证部分中的错误。此错误的常见来源包括COM-interop或PInvoke的用户封送错误,这可能会破坏堆栈。
它出现在Foo的这一行:
string s = o.ToString();
如果我注释掉包含Bar的行,并取消注释前一行,那么代码工作正常,并将异常消息写入调试控制台:
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();
我做了些蠢事,还是这个错误?
答案 0 :(得分: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
上为此错误提交反馈报告