[ThreadStatic]
属性はどのように機能しますか?コンパイラーがILを放出してTLSに値を入れたり取得したりすると想定しましたが、逆アセンブリを見ると、そのレベルではそうではないようです。
フォローアップとして、それを非静的メンバーに配置するとどうなりますか?私たちは開発者にその間違いを犯させ、コンパイラは警告を提供しません。
更新
2番目の質問がここで回答:静的C#で変更されたThreadStatic
[ThreadStatic]
属性はどのように機能しますか?コンパイラーがILを放出してTLSに値を入れたり取得したりすると想定しましたが、逆アセンブリを見ると、そのレベルではそうではないようです。
フォローアップとして、それを非静的メンバーに配置するとどうなりますか?私たちは開発者にその間違いを犯させ、コンパイラは警告を提供しません。
更新
2番目の質問がここで回答:静的C#で変更されたThreadStatic
回答:
静的スレッドの実装セマンティクスは、.NET jitコンパイラーでは、ILレベル未満です。VB.NETやC#のようにILに出力するコンパイラーは、ThreadStatic属性を持つ変数を読み書きできるILコードを出力するために、Win32 TLSについて何も知る必要はありません。C#が知る限り、変数について特別なことは何もありません。これは、データを読み書きするための場所にすぎません。それがそれに属性を持っているという事実はC#に影響を与えません。C#は、そのシンボル名のIL読み取りまたは書き込み命令を発行することを知る必要があるだけです。
「重いリフティング」は、特定のハードウェアアーキテクチャでILを機能させるコアCLRによって実行されます。
これは、不適切な(静的でない)シンボルに属性を設定してもコンパイラーからの反応が得られない理由も説明します。コンパイラーは、属性が必要とする特別なセマンティクスを知りません。ただし、FX / Copなどのコード分析ツールはそれについて知っている必要があります。
別の見方:CILは一連のストレージスコープを定義します:静的(グローバル)ストレージ、メンバーストレージ、スタックストレージ。TLSがリストに含まれている必要はないため、TLSはリストに含まれていません。シンボルがTLS属性でタグ付けされているときに、ILの読み取りおよび書き込み命令でTLSにアクセスできる場合、ILにTLSの特別な表現または処理が必要なのはなぜですか?必要ありません。
[ThreadStatic]属性はどのように機能しますか?
あなたはThreadStaticでマークされたフィールドと考えることができますでスレッドにアタッチされ、その存続期間はスレッドの存続期間に匹敵する。
したがって、疑似コードでThreadStatic
は(セマンティクスにより)スレッドにキー値をアタッチするのと似ています。
Thread.Current["MyClass.myVariable"] = 1;
Thread.Current["MyClass.myvariable"] += 1;
しかし、構文は少し簡単です:
class MyClass {
[ThreadStatic]
static int myVariable;
}
// .. then
MyClass.myVariable = 1;
MyClass.myVariable += 1;
非静的メンバーに配置するとどうなりますか?
私はそれが無視されていると思います:
class A {
[ThreadStatic]
public int a;
}
[Test]
public void Try() {
var a1 = new A();
var a2 = new A();
a1.a = 5;
a2.a = 10;
a1.a.Should().Be.EqualTo(5);
a2.a.Should().Be.EqualTo(10);
}
さらにThreadStatic
、通常の静的フィールドと比較して、同期メカニズムを必要としないことにも言及する価値があります(状態が共有されないため)。
"MyClass.myVariable"
ある必要がありますね。
TransactionScope
、彼らはスコープ(のためにそこにもののすべての種類を格納しreferencesource.microsoft.com/#System.Transactions/System/...)
[ThreadStatic]は、各スレッドで同じ変数の分離バージョンを作成します。
例:
[ThreadStatic] public static int i; // Declaration of the variable i with ThreadStatic Attribute.
public static void Main()
{
new Thread(() =>
{
for (int x = 0; x < 10; x++)
{
i++;
Console.WriteLine("Thread A: {0}", i); // Uses one instance of the i variable.
}
}).Start();
new Thread(() =>
{
for (int x = 0; x < 10; x++)
{
i++;
Console.WriteLine("Thread B: {0}", i); // Uses another instance of the i variable.
}
}).Start();
}