3
我有一個動態模塊,它會在我的應用程序運行時將類型添加到它。該模塊通過以下代碼創建:動態模塊何時可以有類型加載異常?
var assemblyName = new AssemblyName("MyAssembly");
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
MyClass.RuntimeBoundDerivedTypesModule = assemblyBuilder.DefineDynamicModule("MainModule");
應用程序的其他部分有時也會在模塊的程序集上調用GetTypes()。偶爾,當發生這種情況時,我會爲動態模塊中的某個類型獲取TypeLoadException。棧跟蹤是:
at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
at System.Reflection.RuntimeModule.GetTypes()
at System.Reflection.Assembly.GetTypes()
我的問題是:什麼可能會導致此異常?運行時模塊是否真的是線程安全的,或者當類型通過創建被中途調用時,GetTypes()被調用時會有競爭條件嗎?
編輯:這裏有一小段代碼可以爲我可靠地重現錯誤。現在看來,如果GetTypes()被調用DefineType()和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());