2012-03-28 85 views
1

我正在寻找一种方法来解释通过调用ReferenceEquals()来抛出高级业务逻辑是不合理的。比较线程的相等性

下面是一个代码片段,我有一个问题(在方法,设计前提抛出,如果我们是在一个错误的线程):

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

它是可靠的,而不是写:

if (Thread.CurrentThread != RequestHandlerThread) 

我建议在比较中使用ManagedThreadIds,基于我在教程中常见的内容。对手说,参照平等的比较似乎更加面向对象。

这里(大致)是我在.NET 4.0的System.Object的Reflector视图中看到的。请记住,Thread类是密封的,并且对于operator ==没有重载。

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 ==”的实现之外的任何地方使用。 – 2012-03-28 17:30:22

+0

在Equals()'实现中使用的ReferenceEquals() – sll 2012-03-28 20:17:57

回答

0

简短回答:

使用ManagedThreadId属性进行比较。

简单的例子:

假设我们有一个名为StackOverflow.MessageThread类。程序员胖手指一个函数的前提条件,说Debug.Assert(Thread.CurrentThread == messageThread)。前提条件在运行时失败。如果开发人员将达到ManagedThreadId,他会在编辑时发现这是不可能的,并且会在开发周期的早期解决问题。

2

你是对的。正如你的反映查询所示,这两种方式是等价的(除了以对手方式进行额外的方法调用)

6

试图不鼓吹,但是... 一般来说,如果有一个身份属性要使用, case

Thread.ManagedThreadId 

它应该用于相等比较,除非执行代码存在性能约束。指针比较的语义与平等很不相同。另外,指针比较依赖于mscorlib中Thread的实现。

+0

欢迎并感谢KeithP的有趣解答。 – 2012-03-28 21:54:30

1

我可以看到一个实现如何使用两个不同的引用,但仍然指向内部的同一个线程。假设参考平等意味着威胁是平等的,这很好。但是,这并不意味着如果它们不同于对象在语义上不相等。仅此一点就足以反对在业务逻辑中比较参考的做法。

+0

不,因为目前引用** do **很可能指向同一个实例。然而,这并不是对未来的保证。一个通用的答案有点太简单了,你可以创建一个数字的两个实例并对它们进行比较,即使它们是相等的,也可以看到它们在参考时失败(呃,呃!)。 – 2012-03-29 13:32:34