use*_*375 5 c# multithreading automapper
在我们当前的项目中,我们在类的静态构造函数中注册映射,这些构造函数由多个线程调用.静态构造函数中的映射仅与该类相关.但是仍然可以同时运行多个CreateMap调用.此外,偶尔(主要是复制/过去的问题)相同的映射可以在不同类的静态构造函数中注册.
我试图谷歌是否Mapper.CreateMap是线程安全的.我发现只有以下内容:
在2012年AutoMapper线程安全的Map Map.Map中,有一个注释,nemesv的回答是CreateMap不是线程安全的,它永远不会.
但是我发现GitHub上的一个问题静态DynamicMap和CreateMap API应该是 2014年的线程安全标记,在3.2版本中标记为已关闭.这表明CreateMap现在应该是线程安全的.
你能确认CreateMap是线程安全的吗?我进行了一些测试,它看起来应该是,但如果有更深入了解的人可以确认这些信息就可以了.
编辑 经过一些额外的测试后,似乎CreateMap行为非常有趣:
我使用以下代码进行测试
public void Test()
{
var items = new List<EntityA>();
for (int i = 0; i < 100000; i++)
{
items.Add(new EntityA { FirstName = "A" + i });
}
ManualResetEvent stopChangingMappingFunction = new ManualResetEvent(false);
Thread t1 = new Thread(() =>
{
int i = 1;
while (true)
{
if (stopChangingMappingFunction.WaitOne(TimeSpan.Zero))
return;
var i1 = i++;
Mapper.CreateMap<EntityA, EntityB>().ForMember(x => x.Age, y => y.ResolveUsing(new Func<EntityA, object>(a => i1)));
}
});
Thread t2 = new Thread(() =>
{
int i = -1;
while (true)
{
if (stopChangingMappingFunction.WaitOne(TimeSpan.Zero))
return;
var i1 = i--;
Mapper.CreateMap<EntityA, EntityB>().ForMember(x => x.Age, y => y.ResolveUsing(new Func<EntityA, object>(a => i1)));
}
});
List<int> distinctAges1 = null;
List<int> distinctAges2 = null;
Thread t3 = new Thread(() =>
{
Thread.Sleep(1000);
var res = Mapper.Map<IList<EntityA>, IList<EntityB>>(items);
distinctAges1 = res.Select(x => x.Age).Distinct().ToList();
Thread.Sleep(1000);
var res2 = Mapper.Map<IList<EntityA>, IList<EntityB>>(items);
distinctAges2 = res.Select(x => x.Age).Distinct().ToList();
stopChangingMappingFunction.Set();
});
t1.Start();
t2.Start();
t3.Start();
t1.Join();
t2.Join();
t3.Join();
Console.WriteLine("First Mapping: " + string.Join(", ", distinctAges1.ToArray()));
Console.WriteLine("Second Mapping: " + string.Join(", ", distinctAges2.ToArray()));
Console.ReadKey();
}
public class EntityA
{
public string FirstName { get; set; }
}
public class EntityB
{
public string FirstName { get; set; }
public int Age { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
在我调用第一个Map方法的所有测试中,这意味着CreateMap被冻结,并且不能再对映射函数进行更改(distinctAges1始终是一个唯一值,而且相同的值在distinctAges2中).从两个线程更改地图功能有时会导致Age从负数到正数的交替值增加(测试以不同年龄的高值结束).但有时行为完全不同,年龄迭代停止在1或-1的值.如果这个映射函数从更多线程更改,似乎有一些内部机制冻结映射函数的更改.但这种情况并非在100%的情况下发生
CreateMap 是线程安全的。这并不意味着您调用 CreateMap 的代码是。每个 AppDomain 只能调用一次 CreateMap,通常的方法是这样的:https: //github.com/jbogard/ContosoUniversity/blob/master/src/ContosoUniversity/Infrastruct/Mapping/Au toMapperBootstrapper.cs
地图不应使用通过闭包传入的任何上下文数据。上面的代码一开始就是糟糕的地图,您应该重构它们以使用上下文数据的内置方法/sf/answers/2222789341/
| 归档时间: |
|
| 查看次数: |
1476 次 |
| 最近记录: |