System.Linq.Dynamic .Select(“new ...”) 似乎不是线程安全的

发布于 2024-11-30 19:05:29 字数 1429 浏览 0 评论 0原文

我从这里获取了 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浮生未歇 2024-12-07 19:05:29

我执行了以下操作(需要 .NET 4 或更高版本才能使用 System.Collections.Concurrent):

  • classes 字段更改为 ConcurrentDictionary< /code> ,
  • 删除了所有 ReaderWriterLock rwLock 字段以及引用它的所有代码,
  • GetDynamicClass 更新为:

    public Type GetDynamicClass(IEnumerable 属性) {
        var 签名 = 新签名(属性);
        返回classes.GetOrAdd(signature, sig => CreateDynamicClass(sig.properties));
    }
    
  • 删除了classCount字段并更新了CreateDynamicClass以使用类。改为计数:

    类型 CreateDynamicClass(DynamicProperty[] 属性) {
        字符串类型名称 = "DynamicClass" + Guid.NewGuid().ToString("N");
    ...
    

I did the following (requires .NET 4 or later to use System.Collections.Concurrent):

  • changed the classes field to a ConcurrentDictionary<Signature, Type> ,
  • removed all the ReaderWriterLock rwLock field and all the code referring to it,
  • updated GetDynamicClass to:

    public Type GetDynamicClass(IEnumerable<DynamicProperty> properties) {
        var signature = new Signature(properties);
        return classes.GetOrAdd(signature, sig => CreateDynamicClass(sig.properties));
    }
    
  • removed the classCount field and updated CreateDynamicClass to use classes.Count instead:

    Type CreateDynamicClass(DynamicProperty[] properties) {
        string typeName = "DynamicClass" + Guid.NewGuid().ToString("N");
    ...
    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文