简体   繁体   English

比较线程是否相等

[英]Comparing Threads for equality

I am looking for a way to explain that it's unreasonable to sprinkle high-level business logic with calls to ReferenceEquals(). 我正在寻找一种方法来解释通过调用ReferenceEquals()来使用高级业务逻辑是不合理的。

Here's a code snippet that I have a problem with (precondition in a method, designed to throw if we're on a wrong thread): 这是一个我遇到问题的代码片段(方法中的前置条件,如果我们在一个错误的线程上,则设计为抛出):

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

Is it reliable to write this instead: 写这个是可靠的:

if (Thread.CurrentThread != RequestHandlerThread)

I suggested to use ManagedThreadIds in the comparison based on what I commonly see in tutorials. 我建议在比较中使用ManagedThreadIds基于我在教程中常见的内容。 Adversary says that comparison for reference equality seems more object-oriented. 对手说参考平等的比较看起来更像面向对象。

Here's (roughly) what I saw in Reflector's view of System.Object with .NET 4.0. 这是(大致)我在Reflector的.NET 4.0 System.Object视图中看到的。 Keep in mind that Thread class is sealed, and has no overload for operator==. 请记住,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)));
}

Here are some basic tests, verifying operation on thread pool... Did I miss any significant tests? 以下是一些基本测试,验证线程池上的操作......我是否错过了任何重要的测试?

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("");
      }
   }
}

Trying not to preach, but ... In general, if there is an identity property to use, in this case 试着不要讲道,但是......一般来说,如果有一个身份属性可以使用,在这种情况下

Thread.ManagedThreadId

it should be used for equality comparisons unless there is a performance constraint for the executing code. 它应该用于相等比较,除非执行代码存在性能约束。 The semantics of a pointer comparison are a lot different than equality. 指针比较的语义与等式有很大不同。 Also, the pointer comparison is dependent upon the implementation of Thread in mscorlib. 此外,指针比较取决于mscorlib中Thread的实现。

You are correct. 你是对的。 As your reflection inquiry shows, the two ways are equivalent (barring an extra method call in the adversary's way) 正如您的反思查询所示,这两种方式是等效的(除非以对手的方式进行额外的方法调用)

I could see how an implementation could use two references that are different, but would still point to the same thread internally. 我可以看到一个实现如何使用两个不同的引用,但仍然会在内部指向同一个线程。 It's fine to assume that reference equality means that the threats are equal. 假设参考平等意味着威胁相等,这是可以的。 But that does not mean that if they are different that the objects don't equal semantically. 但这并不意味着如果它们不同,那么对象在语义上就不相等。 This alone should be enough to advice against the practice of comparing references in business logic. 仅此一点就足以建议不要比较业务逻辑​​中的引用。

Short answer: 简短回答:

Use ManagedThreadId property for comparisons. 使用ManagedThreadId属性进行比较。

Simple Example: 简单示例:

Imagine we have a class called StackOverflow.MessageThread. 想象一下,我们有一个名为StackOverflow.MessageThread的类。 Programmer fat-fingers a precondition for a function, saying Debug.Assert(Thread.CurrentThread == messageThread). 程序员胖手指一个函数的前提条件,说Debug.Assert(Thread.CurrentThread == messageThread)。 Precondition fails at runtime. 前提条件在运行时失败。 If the dev would reach for ManagedThreadId, he'd find out at edit-time that it's impossible, and would fix the problem earlier in the development cycle. 如果dev将达到ManagedThreadId,他会在编辑时发现它是不可能的,并且会在开发周期的早期解决问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM