2016-11-05 9 views
2

Entity Frameworkクエリの一部であるWhere節にそれらを渡すために、(LinqKitで)動的に生成される式をキャッシュします。式ツリーはスレッドセーフですか?

だから私は、複数のスレッドがApplyを呼び出し、その後、並行してこれらのクエリを実行するため

private static Expression<Func<T, bool>> _expression; // Gets a value at runtime 

public IQueryable<T> Apply(IQueryable<T> query) 
{   
    return query.Where(_expression); // Here _expression already has a value 
} 

のようなものが安全ですか? Expression<TDelegate>クラスはスレッドセーフですか?

ドキュメントは、標準「このタイプのメンバー(Visual BasicではShared)すべてのパブリックstaticは、スレッドセーフです...」を与える

+1

[スレッドセーフとは何ですか?](https://blogs.msdn.microsoft.com/ericlippert/2009/10/19/what-is-this-thing-あなたの呼び出しスレッドセーフ/) –

+0

私にはあまりにも哲学的に見えます。 2つのパラレル問合せが同じ述語式オブジェクトをWhere部分に持つ場合、2つのパラレル問合せが機能するかどうかを知りたいだけです。 – user764754

+0

AFAIK、式ツリーは不変であり、したがってスレッドセーフです。 –

答えて

12

式ツリー自体は不変です。しかし、彼らはdoが変更されたものを参照することができます。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Linq.Expressions; 

public class Test 
{ 
    static void Main() 
    { 
     int multiplier = 3; 
     IQueryable<int> values = new List<int> { 1, 2 }.AsQueryable(); 
     Expression<Func<int, int>> expression = x => x * multiplier; 

     // Prints 3, 6 
     foreach (var item in values.Select(expression)) 
     { 
      Console.WriteLine(item); 
     } 

     multiplier = 5; 

     // Prints 5, 10 
     foreach (var item in values.Select(expression)) 
     { 
      Console.WriteLine(item); 
     } 
    } 
} 

表現ツリーが変更されないものだけを参照している場合は、それは問題ありません。それはほとんどの状況で起こります。

が変更可能な状態を指しん、もしあるスレッドがその状態を変異させるあなたの式ツリーた場合は、式ツリーを適用し、他のスレッドは、メモリモデルの通常の方法で、変更が表示されない場合があります。

+0

私の場合、彼らはクロージャを使用しません。 t => t.Name == "SomeName"のようなものだけです。だから私はそれが安全だと思います。 – user764754

+1

@ user764754:はい、それは問題ありません。値を変更しない限り、変数をクローズしても問題ありません。 –

関連する問題