NotSupportedException in read-only collection

SyntaxEditor .NET Languages Add-on for WPF Forum

Posted 1 year ago by Tobias Lingemann - Software Devolpment Engineer, Vector Informatik GmbH
Version: 22.1.4
Platform: .NET 4.8
Environment: Windows 10 (64-bit)
Avatar

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 1 year ago]


Best regards, Tobias Lingemann.

Comments (1)

Answer - Posted 1 year ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello,

Since the class is internal, what you are doing is probably best as a workaround.  We'll update how the properties are initialized for the next maintenance release.


Actipro Software Support

The latest build of this product (v24.1.1) was released 2 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.