Сравнение потоков на равенство - PullRequest
2 голосов
/ 28 марта 2012

Я ищу способ объяснить, что нецелесообразно сбрасывать бизнес-логику высокого уровня вызовами ReferenceEquals ().

Вот фрагмент кода, с которым у меня проблема (предварительное условие в методе, предназначенном для выброса, если мы находимся не в том потоке):

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

Надежно ли написать это вместо:

if (Thread.CurrentThread != RequestHandlerThread)

Я предложил использовать ManagedThreadIds в сравнении на основе того, что я часто вижу в руководствах. Противник говорит, что сравнение для референтного равенства кажется более объектно-ориентированным.

Вот (примерно) то, что я увидел в представлении Reflector System.Object с .NET 4.0. Помните, что класс 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("");
      }
   }
}

Ответы [ 4 ]

7 голосов
/ 28 марта 2012

Попытка не проповедовать, но ... В общем, если есть свойство идентификации, которое нужно использовать, в этом случае

Thread.ManagedThreadId

оно должно использоваться для сравнений на равенство, если нет ограничения производительности дляисполняющий код.Семантика сравнения указателей сильно отличается от равенства.Кроме того, сравнение указателей зависит от реализации Thread в mscorlib.

2 голосов
/ 28 марта 2012

Вы правы.Как показывает ваш запрос на отражение, оба пути эквивалентны (исключая дополнительный вызов метода на пути противника)

1 голос
/ 29 марта 2012

Я мог видеть, как реализация может использовать две разные ссылки, но они все равно будут указывать на один и тот же поток внутри.Можно предположить, что эталонное равенство означает, что угрозы равны.Но это не значит, что если они различаются, то объекты не равны семантически.Одного этого должно быть достаточно, чтобы советоваться с практикой сравнения ссылок в бизнес-логике.

0 голосов
/ 29 марта 2012

Краткий ответ:

Используйте свойство ManagedThreadId для сравнения.

Простой пример:

Представьте, что у нас есть класс с именем StackOverflow.MessageThread. Программист толстыми пальцами является предварительным условием для функции, говоря Debug.Assert (Thread.CurrentThread == messageThread). Предварительное условие не выполняется во время выполнения. Если бы разработчик дотянулся до ManagedThreadId, он обнаружил бы во время редактирования, что это невозможно, и исправил бы проблему ранее в цикле разработки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...