
Hi,
we ran into an exception when working with multiple worker threads.
System.NotSupportedException: 'The collection is read-only and cannot be modified.'
ActiproSoftware.Text.Wpf.dll!ActiproSoftware.Text.Utility.SimpleObservableCollection<ActiproSoftware.Text.Languages.DotNet.Reflection.ITypeReference>.CheckReadOnly()
ActiproSoftware.Text.Wpf.dll!ActiproSoftware.Text.Utility.SimpleObservableCollection<ActiproSoftware.Text.Languages.DotNet.Reflection.ITypeReference>.InsertItem(int index = 0, ActiproSoftware.Text.Languages.DotNet.Reflection.ITypeReference item = {ActiproSoftware.Internal.xBt})
ActiproSoftware.Text.Wpf.dll!ActiproSoftware.Text.Utility.SimpleSynchronizedCollection<ActiproSoftware.Text.Languages.DotNet.Reflection.ITypeReference>.InsertItem(int index = 0, ActiproSoftware.Text.Languages.DotNet.Reflection.ITypeReference item = {ActiproSoftware.Internal.xBt})
ActiproSoftware.Text.Addons.DotNet.Wpf.dll!ActiproSoftware.Internal.jBv.p2z.get()
The issue seems to be the initialization of the properties in 'TypeReferenceCollection'. It has three static properties, which are initialized on demand. However the initialization is not thread safe. Since we are close to our next release, I cannot upgrade to a new version.
Therefore I use reflection to initialize the properties manually like this:
private static void WorkaroundThreadSafetyIssue()
{
var it = typeof(ITypeReferenceCollection);
InitializePropertiesWithType(it.Assembly, it);
// Do the same with the Roslyn assembly
var asm = typeof(RoslynBinaryAssemblyLoader).Assembly;
InitializePropertiesWithType(asm, it);
}
private static void InitializePropertiesWithType(Assembly assembly, Type type)
{
var types = assembly.GetTypes().Where(t => t.GetInterfaces().Contains(type)).ToList();
foreach (var methods in types.Select(t => t.GetMethods(BindingFlags.Static | BindingFlags.Public)))
{
methods.Where(p => p.ReturnType == type).Select(p => p.Invoke(obj: null, parameters: null));
}
foreach (var properties in types.Select(t => t.GetProperties(BindingFlags.Static | BindingFlags.Public)))
{
properties.Where(p => p.PropertyType == type).Select(p => p.GetValue(obj: null));
}
}
If you have a better workaround, please let me know.
[Modified 2 years ago]
Best regards, Tobias Lingemann.