2012-03-28 16 views
1

私は、ReferenceEquals()の呼び出しで高水準のビジネスロジックを振りかけるのが無理だと説明する方法を探しています。代わりに、これを書くためにスレッドを同等に比較する

if (!object.ReferenceEquals(Thread.CurrentThread, RequestHandlerThread)) 

それが信頼性はあります:ここで

は、私は(私たちは間違ったスレッドにしている場合はスローするように設計された方法では、前提条件)に問題があるコードスニペットです

if (Thread.CurrentThread != RequestHandlerThread) 

私がチュートリアルでよく見る内容に基づいて、比較でManagedThreadIdsを使用することを提案しました。 Adversaryによれば、参照平等の比較はオブジェクト指向のようだ。

Reflectorが.NET 4.0でSystem.Objectの見たところで見たもの(大まかに)です。 Threadクラスはシールされており、演算子==のオーバーロードはありません。

public static bool ReferenceEquals(object objA, object objB) 
{ 
    return (objA == objB); 
} 

public static bool Equals(object objA, object objB) 
{ 
    return (objA == objB || 
     (objA != null && objB != null && objA.Equals(objB))); 
} 

ここにいくつかの基本的なテストがあり、スレッドプールの動作を確認しています...重要なテストがありませんでしたか?

using System.Threading; 
using System.Diagnostics; 
using System.Threading.Tasks; 

namespace ConsoleApplicationX 
{ 
    class Program 
    { 
     static readonly Thread mainThread; 

     static Program() 
     { 
     mainThread = Thread.CurrentThread; 
     } 

     static void Main(string[] args) 
     { 
     Thread thread = Thread.CurrentThread; 
     if (thread != Thread.CurrentThread) 
      Debug.Fail(""); 

     if(Thread.CurrentThread != thread) 
      Debug.Fail(""); 

     if (thread != mainThread) 
      Debug.Fail(""); 

     var task = Task.Factory.StartNew(() => RunOnBackground(thread)); 
     task.Wait(); 

     var anotherThread = new Thread(new ParameterizedThreadStart(RunInAnotherThread)); 
     anotherThread.Start(thread); 
     } 

     static void RunOnBackground(Thread fromInitial) 
     { 
     if (Thread.CurrentThread == fromInitial) 
      Debug.Fail(""); 

     if (fromInitial != mainThread) 
      Debug.Fail(""); 
     } 

     static void RunInAnotherThread(object fromInitialAsObject) 
     { 
     var fromInitial = (Thread)fromInitialAsObject; 

     if (Thread.CurrentThread == fromInitial) 
      Debug.Fail(""); 

     if (fromInitial != mainThread) 
      Debug.Fail(""); 
     } 
    } 
} 
+1

FWIW、私は個人的にSystem.Object.ReferenceEqualsが "operator =="の実装の外側で使用されているのを見たことがありません。 –

+0

Equals()の実装で使用されるReferenceEquals()の実装 – sll

答えて

0

短い回答:

比較のためにManagedThreadIdプロパティを使用してください。

簡単な例:

我々はStackOverflow.MessageThreadというクラスを持っている想像してみてください。プログラマーはDebug.Assert(Thread.CurrentThread == messageThread)と言って、関数の前提条件を大切にしています。実行時に前提条件が失敗します。開発者がManagedThreadIdに達すると、彼は編集時には不可能であることを知り、開発サイクルの早い段階で問題を解決します。

2

あなたは正しいです。あなたの反射の照会が示すように、2つの方法は同等です(敵の方法で余分なメソッド呼び出しを禁止します)

6

説教しようとしていませんが... 一般的に、ケース

Thread.ManagedThreadId 

実行コードのパフォーマンス制約がない限り、等価比較に使用する必要があります。ポインタ比較のセマンティクスは、等価とは大きく異なります。また、ポインタの比較はmscorlibのThreadの実装に依存します。

+0

面白い答えKeithP、modded upへようこそ。 –

1

実装で異なる2つの参照を使用する方法がわかりましたが、内部的には同じスレッドを指しています。参照平等は、脅威が同等であることを意味すると仮定するのは良いことです。しかし、それは意味が同じではないオブジェクトが異なる場合、オブジェクトが意味的に等しくないことを意味するものではありません。これだけでも、ビジネスロジックの参照を比較する習慣に対してアドバイスするだけで十分です。

+0

いいえ、現在は参照**が**同じインスタンスを指している可能性が高いためです。しかしこれは将来の保証ではありません。一般的な答えはちょっと単純すぎます。数字の2つのインスタンスを作成して比較することができます。それらが同じであっても参照で失敗することがあります(よく、duh!)。 –

関連する問題