0

My main project loads libraries with devices and creates instances for them. After publishing in the Debug mode, the project works fine, the problem appears when it is published in the Release mode. I don't know why, but it doesn't wait for the objects it creates to initialize.

Here is a code snippet:

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)
{
}

And one of the objects that are created:

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()
    {

    }
}

And it didnt wait for properties ConnectorDescriptorBuilderEntry. I did a test and added this initialization to the Initialize() method but it wasn't initialized right there either. And it happens only after some time.

I don't know how, but it worked before, I took over this project from someone else. I didn't change anything in the main project. I just added a new device. It does not throw any errors during initialization. And it eventually initializes everything. There is no asynchronicity here.

Net 4.5

I don't know if the amount of code posted is enough to solve my problem, but maybe someone can tell me where to look for a solution and why it works on Debug and not on Release?

Silny ToJa
  • 1,815
  • 1
  • 6
  • 20
  • 1
    In the absence of a static consrtuctor, it is only guaranteed that the static field `ConnectorDescriptorBuilderEntry` is initialized before first use. See https://stackoverflow.com/questions/710793/how-does-static-field-initialization-work-in-c – Klaus Gütter Mar 23 '21 at 13:51
  • @KlausGütter unfortunately I don't know why the Register() method is not called; When I tried to debug it (when it was initialized in method Initialize()), it was run after using the program some time. – Silny ToJa Mar 23 '21 at 13:57
  • 1
    Try to move the initialization to a static constructor `static WZWCDeviceTesterToolProvider() { ConnectorDescriptorBuilderEntry = ... }` – Klaus Gütter Mar 23 '21 at 14:00
  • @KlausGütter With my not the best English, I didn't understand you first time well, but you are right and your answer solved my problem. – Silny ToJa Mar 24 '21 at 07:24

1 Answers1

1

According to the C# specification, if there is no static constructor, there is no guarantee when a static field is exactly initialized, only that this happens before first use.

15.5.6.2 Static field initialization

The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration (§15.5.6.1). Within a partial class, the meaning of "textual order" is specified by §15.5.6.1. If a static constructor (§15.12) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class.

If there is however a static constructor, it is guaranteed that all static fields are initialized before it runs, which is in turn guaranteed to happen if you instantiate an object of the class or access a static member for the first time.

So to force the initialization of your field, you can add a static constructor:

static WZWCDeviceTesterToolProvider()
{
}
Klaus Gütter
  • 11,151
  • 6
  • 31
  • 36