动态模块时,可以有一个类型的负载例外? [英] When can a dynamic module have a type load exception?

查看:143
本文介绍了动态模块时,可以有一个类型的负载例外?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个动态的模块,它被添加到它作为我的应用程序运行时类型。该模块通过下面的代码创建:

  VAR的AssemblyName =新的AssemblyName(MyAssembly程序); 
VAR assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(的AssemblyName,AssemblyBuilderAccess.Run);
MyClass.RuntimeBoundDerivedTypesModule = assemblyBuilder.DefineDynamicModule(MainModule);

应用程序的其他部分有时也叫GetTypes()在模块的组装。偶尔,当发生这种情况,我得到TypeLoadException为动态模块中的类型之一。堆栈跟踪是:在的System.Reflection

 在System.Reflection.RuntimeModule.GetTypes(RuntimeModule模块)
。 RuntimeModule.GetTypes()在System.Reflection.Assembly.GetTypes
()

我的问题是:什么可能导致此异常?在运行时模块真正线程安全的,或不可能有竞争状态,其中GetTypes()被调用,而一类是中途被创建



编辑:这里有一个小片段代码可靠地再现错误我。现在看来,如果GetTypes()被调用DefineType()和CreateType()之间发生的异常:

  VAR的AssemblyName =新的AssemblyName(MyAssembly程序); 
VAR assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(的AssemblyName,AssemblyBuilderAccess.Run);
ModuleBuilder M = assemblyBuilder.DefineDynamicModule(富);

行动doStuff =()=> {
尝试{
如果(!m.GetTypes()。任何()|| Guid.NewGuid()。GetHashCode的()%2 == 0){
变种T =米DefineType(
的MyType+ Guid.NewGuid()的ToString()更换( - ,),
TypeAttributes.Public |。TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout,
的typeof(对象)
);
Thread.sleep代码(1);
t.CreateType();
}
,否则{
//m.GetTypes(); //有趣的是,这个工作总是
assemblyBuilder.GetTypes();
它的工作!转储()。
}

}赶上(例外前){
Console.WriteLine(除息);
}
};

//在同步模式下,我只看到失败,如果我离开了调用CreateType()。在这种
//情况下,它永远不会奏效
//Enumerable.Range(1,1000)
// .ToList()
// .ForEach(_ =>做东西());

//在异步模式下,我总是看到了Thread.Sleep()失败,有时
//看到他们,如果我把睡眠出来。我经常看到失败的组合和成功了!
VAR线程= Enumerable.Range(1,100)。选择(T =>新的Thread(()=> doStuff()))
.ToList();
threads.ForEach(T => t.Start());
threads.ForEach(T => t.Join());


解决方案

ModuleBuilder而事实上大多数实例方法不是线程安全的在.NET。看到这里的底部: http://msdn.microsoft .COM / EN-US /库/ system.reflection.emit.modulebuilder.aspx


I have a dynamic module which gets types added to it as my application runs. The module is created via the following code:

var assemblyName = new AssemblyName("MyAssembly");
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
MyClass.RuntimeBoundDerivedTypesModule = assemblyBuilder.DefineDynamicModule("MainModule");

Other parts of the application also sometimes call GetTypes() on the module's assembly. Occasionally, when this happens I get TypeLoadException for one of the types in the dynamic module. The stack trace is:

   at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
   at System.Reflection.RuntimeModule.GetTypes()
   at System.Reflection.Assembly.GetTypes()

My question is: what could cause this exception? Are runtime modules truly thread-safe or can there be race conditions where GetTypes() gets called while a type is partway through being created?

EDIT: here's a small snippet of code that reproduces the bug reliably for me. It now seems that the exception occurs if GetTypes() is called between DefineType() and CreateType():

var assemblyName = new AssemblyName("MyAssembly");
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder m = assemblyBuilder.DefineDynamicModule("foo");

Action doStuff = () => {
    try {
        if (!m.GetTypes().Any() || Guid.NewGuid().GetHashCode() % 2 == 0) {
            var t = m.DefineType(
                "MyType" + Guid.NewGuid().ToString().Replace("-", ""),
                TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout,
                typeof(object)
            );
            Thread.Sleep(1);
            t.CreateType();
        }
        else {
            //m.GetTypes(); // interestingly, this always works
            assemblyBuilder.GetTypes();
            "it worked!".Dump();
        }

    } catch (Exception ex) {
        Console.WriteLine(ex);
    }
};

// in synchronous mode, I only see failures if I leave out the call to CreateType(). In that
// case, it never works
//Enumerable.Range(1, 1000)
//  .ToList()
//  .ForEach(_ => doStuff());

// in the async mode, I always see failures with Thread.Sleep() and sometimes
// see them if I take the sleep out. I often see a mix of failures and "It worked!"
var threads = Enumerable.Range(1, 100).Select(t => new Thread(() => doStuff()))
    .ToList();
threads.ForEach(t => t.Start());
threads.ForEach(t => t.Join());

解决方案

ModuleBuilder and in fact most instance methods are not thread safe in .Net. See here at the bottom: http://msdn.microsoft.com/en-us/library/system.reflection.emit.modulebuilder.aspx

这篇关于动态模块时,可以有一个类型的负载例外?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆