4

[ThreadStatic].NET フレームワークのさまざまな場所で使用され、さまざまな機能にアンビエント コンテキストを提供します (たとえばTransaction.Current、これは に使用されTransactionScopeます)。

残念ながら、これはスレッド ジャグリングを行う機能 (ASP.NET、async キーワード コード) がスレッドを切り替えるが、 をコピーしないことを意味TransactionScopeTransactionScopeます

スレッドの切り替え中に状態を正しくコピーする別のメカニズムCallContext.LogicalGetData(詳細はこちら) があります (少なくとも .NET 4.5 では)。TransactionScopeよりもこれを使用した方が良いように思えます[ThreadStatic]

を使用している機能が[ThreadStatic]、下位互換性を必要とする既存の機能ではなく、今日作成されたものである場合、それらは を使用して作成されCallContext.(G|S)etLogicalDataますか?

4

2 に答える 2

1

はい。当時は良いアイデアのように思えたに違いありませんが、[ThreadStatic] は開発者を誤った安心感に陥れます。ThreadStatic フィールドには、グローバル変数の欠点の多くがあり、唯一の利点 (異なるスレッドがグローバルなものの独自のインスタンスを持っている) には、対応する欠点 (スレッドを切り替えるとそのものが消える) があります。これは勝利ではありません。グローバルは最悪であり、スレッド静的グローバルは通常のグローバルと同じくらい最悪です。

私はかなり大規模なコード ベースに取り組んでおり、数年前から数十人の開発者 (過去数年でチームを離れた人ができれば数百人) がいて、定期的に [ThreadStatic] に悩まされています。裏で、ThreadStatic グローバルを使用するコードが大量にありますが、ワーカー スレッドで何かを行うと、もちろん中断します。私が言ったように、当時はそれが良いアイデアのように思えたのは確かです...しかし、今ではそれが私たちを買ったよりもはるかに多くの費用がかかりました.

別の方法は、同じオブジェクト (HttpContext、Transaction など) を、それに依存するすべてのメソッドに渡すことです。それにはより多くのタイピングが必要ですが、私の控えめな意見では、長期的にはまだ優れています.

于 2014-11-04T07:31:03.547 に答える
1

実際には、それらには非常に異なるユースケースがあります。

  • ThreadStaticawaitまたは同様のコンテキスト スイッチを介して値を転送することはできません。
  • CallContextスレッドごとに値を保持することはできません。

ご覧のとおり、一方を他方に置き換えることはできません。ThreadStatic低レベルのプリミティブです。CallContextetcが登場してから、そのユースケースは減っていないと思います。その使用例は非常に小さいことに注意してください-最後に使用したのはおそらく2年以上前だと思います.

私はTransaction.CurrentTLS の悪用のようなものを特徴付けます。このように設計されたことはありませんでした。そのため、TLS が非同期を破るように見えたのは、そもそも非同期に使用されるべきではなかったからです。

于 2014-11-04T07:57:53.057 に答える