【问题标题】:Comparing Threads for equality比较线程是否相等
【发布时间】:2012-03-28 17:23:35
【问题描述】:

我正在寻找一种方法来解释在调用 ReferenceEquals() 时添加高级业务逻辑是不合理的。

这是我遇到问题的代码 sn-p(方法中的前提条件,旨在在我们在错误的线程上时抛出):

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

这样写可靠吗:

if (Thread.CurrentThread != RequestHandlerThread)

根据我在教程中经常看到的内容,我建议在比较中使用 ManagedThreadIds。 Adversary 说引用相等的比较似乎更面向对象。

这是(大致)我在 Reflector 的 System.Object 与 .NET 4.0 视图中看到的内容。请记住,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("");
      }
   }
}

【问题讨论】:

  • FWIW,我个人从未见过 System.Object.ReferenceEquals 在 "operator ==" 实现之外的任何地方使用。
  • ReferenceEquals() 用于Equals() 实现

标签: c# .net multithreading coding-style


【解决方案1】:

尽量不说教,但是... 一般来说,如果有一个身份属性要使用,在这种情况下

Thread.ManagedThreadId

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

【讨论】:

  • 欢迎并感谢 KeithP 的有趣回答,已修改。
【解决方案2】:

你是对的。正如您的反射查询所示,这两种方式是等效的(除非以对手的方式调用额外的方法)

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 否,因为当前引用 do 很可能指向同一个实例。然而,这并不能保证未来。一个通用的答案有点太简单了,您可以创建一个数字的两个实例并比较它们,即使它们相等,它们也会在引用时失败(嗯,呃!)。
    【解决方案4】:

    简答:

    使用 ManagedThreadId 属性进行比较。

    简单示例:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-13
      • 2015-09-16
      • 2013-08-18
      • 2016-10-20
      • 1970-01-01
      • 2021-09-14
      • 2023-03-11
      相关资源
      最近更新 更多