TypeDescriptor.GetProperties()始终返回相同的PropertyDescriptorCollection引用。导致并行处理问题

时间:2018-03-02 05:26:43

标签: c# multithreading reflection parallel-processing contention

前言:我正在努力将库迁移到并行处理数据,并且PropertyDescriptor.GetValue()上的线程之间存在85%以上的争用,从而在多个核心上进行并行处理与处理单个核心相同,有时甚至更糟。

问题:

当调用TypeDescriptor.GetProperties(Type)时,它似乎返回对相同PropertyDescriptorCollection的相同引用,它对所有相同的PropertyDescriptor对象具有相同的引用。这是有问题的,因为我需要为每个线程设置新的PropertyDescriptor集。共享相同的资源会导致线程不断相互阻塞。

并发性分析输出: enter image description here

粗略示例:

    public static void Test()
    {
        var class1 = new ExampleClass();
        var class2 = new ExampleClass();

        var test1 = TypeDescriptor.GetProperties(typeof(ExampleClass));
        var test2 = TypeDescriptor.GetProperties(typeof(ExampleClass));
        Console.WriteLine(Object.ReferenceEquals(test1, test2));
        int i = 0;
        foreach(PropertyDescriptor item in test1)
        {
            Console.WriteLine(Object.ReferenceEquals(test1[i], test2[i]));
            i++;
        }
    }

在这种情况下,每个Object.ReferenceEquals都将返回true。显示它们都指向相同的对象,并且不是不同的。当多个线程在同一GetValue()对象上调用PropertyDescriptor时,这会导致严重的性能问题。

如何为每个对象属性获取全新的PropertyDescriptor个对象?

注意: PropertyInfo通过myType.GetProperties()检索到同样的问题。它返回的PropertyInfo引用相同的对象,所以即使是执行缓存。

其他信息/调查结果:

  • 属性getter的MethodInfo也缓存在PropertyInfo内。因此,获取和调用该方法是不可并行化的,因为它将依赖于所有线程的相同MethodInfo实例。
  • PropertyDescriptor ReflectPropertyDescriptor}在GetValue()期间经历的过程使用Type.GetProperty()RunTimeType.GetProperty()),它使用属性信息缓存返回结果。
    • 这意味着PropertyDescriptorPropertyInfo似乎使用相同的共享缓存来返回属性信息实例,它们都用于访问属性getter方法(也是缓存的)。

TL; DR:它一直缓存。

0 个答案:

没有答案