Skip to content

Concurrency issue in TypeDescriptor.GetConverter(type) #30024

Closed
@PawelGerr

Description

@PawelGerr

TypeDescriptor.GetConverter(type) returns different results when calling on multiple threads with the same type and this type has a custom TypeDescriptionProvider.

This issue is reproducible with target frameworks netcoreapp2.2 and net472 on window 10 x64.

Repro

I'm calling the method on 10 threads and print the fetched type converter at the end.

Expected output

All 10 calls return MyTypeConverter

Actual output

The method return both TypeConverter and MyTypeConverter in random order like the following:

TypeConverter
TypeConverter
TypeConverter
MyTypeConverter
TypeConverter
TypeConverter
TypeConverter
TypeConverter
TypeConverter
TypeConverter

The good thing is that the method is returning MyTypeConverter after the concurrent calls are finished. The bad thing is that there are libs (like newtonsoft.json) that are caching the type descriptors. If the cache of 3rd party lib is initialized with wrong descriptor then the application is broken until restart.

Program.cs

public class Program
{
   public static async Task Main()
   {
      var tasks = new Task<TypeConverter>[10];

      for (var i = 0; i < tasks.Length; i++)
      {
         tasks[i] = new Task<TypeConverter>(() => TypeDescriptor.GetConverter(typeof(MyClass)));
      }

      foreach (var t in tasks)
      {
         t.Start();
      }

      foreach (var conv in await Task.WhenAll(tasks))
      {
         Console.WriteLine(conv.GetType().Name);
      }
   }
}

[TypeDescriptionProvider(typeof(MyClassTypeDescriptionProvider))]
public class MyClass
{
}

public class MyClassTypeDescriptionProvider : TypeDescriptionProvider
{
   public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
   {
      return new MyClassTypeDescriptor();
   }
}

public class MyClassTypeDescriptor : CustomTypeDescriptor
{
   public override TypeConverter GetConverter()
   {
      return new MyTypeConverter();
   }
}

public class MyTypeConverter : TypeConverter
{
}

.csproj-file

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>netcoreapp2.2</TargetFramework>
        <OutputType>EXE</OutputType>
    </PropertyGroup>
</Project>

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions