System.Linq.Dynamic .Select(“new ...”) 似乎不是线程安全的
我从这里获取了 System.Linq.Dynamic.DynamicQueryable : http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
我遇到的问题是在如下所示的代码中:
var results = dataContext.GetTable<MyClass>.Select("new (MyClassID, Name, Description)").Take(5);
看来,如果该行代码由多个线程几乎同时执行,则 Microsoft 的动态 Linq 代码会在其 ClassFactory.GetDynamicClass() 中崩溃方法,如下所示:
public Type GetDynamicClass(IEnumerable<DynamicProperty> properties)
{
rwLock.AcquireReaderLock(Timeout.Infinite);
try
{
Signature signature = new Signature(properties);
Type type;
if (!classes.TryGetValue(signature, out type))
{
type = CreateDynamicClass(signature.properties);
classes.Add(signature, type); // <-- crashes over here!
}
return type;
}
finally
{
rwLock.ReleaseReaderLock();
}
}
崩溃是一个简单的字典错误:“已添加具有相同键的项目。”
在Ms代码中,rwLock变量是一个ReadWriterLock类,但它没有做任何事情来阻止多个线程进入类。TryGetValue() if语句,所以很明显,Add将失败。
我可以在创建两个或多个尝试执行 Select("new") 语句的线程的任何代码中很容易地复制此错误。
无论如何,我想知道是否有其他人遇到过这个问题,以及是否有我可以实施的修复或解决方法。
谢谢。
I grabbed System.Linq.Dynamic.DynamicQueryable from here:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
The issue that I am running into is in code that looks like this:
var results = dataContext.GetTable<MyClass>.Select("new (MyClassID, Name, Description)").Take(5);
It appears that if that line of code is executed by multiple threads near simultaneously, Microsoft's dynamic Linq code crashes in their ClassFactory.GetDynamicClass() method, which looks like this:
public Type GetDynamicClass(IEnumerable<DynamicProperty> properties)
{
rwLock.AcquireReaderLock(Timeout.Infinite);
try
{
Signature signature = new Signature(properties);
Type type;
if (!classes.TryGetValue(signature, out type))
{
type = CreateDynamicClass(signature.properties);
classes.Add(signature, type); // <-- crashes over here!
}
return type;
}
finally
{
rwLock.ReleaseReaderLock();
}
}
The crash is a simple dictionary error: "An item with the same key has already been added."
In Ms code, The rwLock variable is a ReadWriterLock class, but it does nothing to block multiple threads from getting inside classes.TryGetValue() if statement, so clearly, the Add will fail.
I can replicate this error pretty easily in any code that creates a two or more threads that try to execute the Select("new") statement.
Anyways, I'm wondering if anyone else has run into this issue, and if there are fixes or workarounds I can implement.
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我执行了以下操作(需要 .NET 4 或更高版本才能使用
System.Collections.Concurrent
):classes
字段更改为ConcurrentDictionary< /code> ,
ReaderWriterLock rwLock
字段以及引用它的所有代码,将
GetDynamicClass
更新为:删除了
classCount
字段并更新了CreateDynamicClass
以使用类。改为计数:
I did the following (requires .NET 4 or later to use
System.Collections.Concurrent
):classes
field to aConcurrentDictionary<Signature, Type>
,ReaderWriterLock rwLock
field and all the code referring to it,updated
GetDynamicClass
to:removed the
classCount
field and updatedCreateDynamicClass
to useclasses.Count
instead: