使用 Activator.CreateInstance() 创建的对象不会等待整个对象在 Release 上初始化
Posted
技术标签:
【中文标题】使用 Activator.CreateInstance() 创建的对象不会等待整个对象在 Release 上初始化【英文标题】:Objects created with Activator.CreateInstance() do not wait for the entire object to be initialized on Release 【发布时间】:2021-03-23 13:39:19 【问题描述】:我的主项目加载带有设备的库并为它们创建实例。在Debug模式下发布后,项目工作正常,在Release模式下发布时出现问题。我不知道为什么,但它不会等待它创建的对象初始化。
这是一个代码sn-p:
try
AssemblyName name = AssemblyName.GetAssemblyName(module);
Type[] iLoadTypes = (from t in Assembly.Load(name).GetExportedTypes()
where !t.IsInterface && !t.IsAbstract
where typeof(IDevice).IsAssignableFrom(t)
select t).ToArray();
if (iLoadTypes.Length > 0)
IDevice[] instantiatedDevices =
iLoadTypes.Select(t => (IDevice)Activator.CreateInstance(t)).ToArray();
foreach (var device in instantiatedDevices)
Devices.Add(device);
iLoadTypes = (from t in Assembly.Load(name).GetExportedTypes()
where !t.IsInterface && !t.IsAbstract
where typeof(IDeviceToolProvider).IsAssignableFrom(t)
select t).ToArray();
IDeviceToolProvider[] instantiatedProviders =
iLoadTypes.Select(t => (IDeviceToolProvider)Activator.CreateInstance(t)).ToArray();
foreach (var provider in instantiatedProviders)
var device = Devices.Find(dev => dev.GetType() == provider.DeviceType);
if (device == null)
continue;
provider.Device = device;
if (!DeviceToolProviders.ContainsKey(device))
DeviceToolProviders[device] = new List<IDeviceToolProvider>();
DeviceToolProviders[device].Add(provider);
provider.Initialize();
catch (Exception ex)
以及创建的对象之一:
public class WZWCDeviceTesterToolProvider : IDeviceToolProvider
internal static readonly UserSettingEntry<ConnectionDescriptorBuilder> ConnectorDescriptorBuilderEntry =
UserSettingEntry.Register("ConnectorDescriptorBuilderEntry", typeof(WZWCDeviceTesterToolProvider),
new UserSettingEntryMetadata<ConnectionDescriptorBuilder>());
public string Name get return "WZW";
...
public void Initialize()
它没有等待属性ConnectorDescriptorBuilderEntry
。我做了一个测试并将这个初始化添加到 Initialize()
方法中,但它也没有在那里初始化。它只会在一段时间后发生。
我不知道是怎么做到的,但它之前是有效的,我从别人那里接手了这个项目。我没有更改主项目中的任何内容。我刚刚添加了一个新设备。它在初始化期间不会抛出任何错误。它最终会初始化所有内容。这里没有异步。
净 4.5
我不知道发布的代码量是否足以解决我的问题,但也许有人可以告诉我在哪里寻找解决方案以及为什么它适用于 Debug 而不是 Release?
【问题讨论】:
在没有静态构造函数的情况下,只保证静态字段ConnectorDescriptorBuilderEntry
在第一次使用前被初始化。见***.com/questions/710793/…
@KlausGütter 不幸的是我不知道为什么没有调用 Register() 方法;当我尝试调试它时(当它在方法 Initialize() 中初始化时),它在使用程序一段时间后运行。
尝试将初始化移动到静态构造函数static WZWCDeviceTesterToolProvider() ConnectorDescriptorBuilderEntry = ...
@KlausGütter 由于我的英语不是最好的,我第一次听不懂你,但你是对的,你的回答解决了我的问题。
【参考方案1】:
根据C# specification,如果没有静态构造函数,则无法保证静态字段何时被精确初始化,只能在第一次使用之前发生。
15.5.6.2 静态字段初始化
类的静态字段变量初始化器对应于 以文本顺序执行的任务序列 它们出现在类声明中(§15.5.6.1)。在一个 部分类,“文本顺序”的含义由 §15.5.6.1。如果类中存在静态构造函数(第 15.12 节), 静态字段初始化器的执行发生在紧接之前 执行该静态构造函数。 否则,静态字段 初始化器在依赖于实现的时间执行 第一次使用该类的静态字段。
但是,如果有静态构造函数,则保证所有静态字段在运行之前都已初始化,这反过来又保证在您实例化类的对象或第一次访问静态成员时发生。
所以要强制初始化你的字段,你可以添加一个静态构造函数:
static WZWCDeviceTesterToolProvider()
【讨论】:
以上是关于使用 Activator.CreateInstance() 创建的对象不会等待整个对象在 Release 上初始化的主要内容,如果未能解决你的问题,请参考以下文章
在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?
Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)