Резьба и розетки - PullRequest
       40

Резьба и розетки

1 голос
/ 17 ноября 2009

У меня есть следующее:

   ThreadStart startThread =
     delegate
     {
             mySocket.StartListen();
     };

mySocket теперь зацикливается на Listen (), когда I:

new Thread(startThread).Start();

Вот StartListen:

public void StartListen()
{
 Object locker = new Object();

 // Lock resources
 lock (locker)
 {
  S = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork,
       System.Net.Sockets.SocketType.Stream,
       System.Net.Sockets.ProtocolType.Tcp);
  S.Blocking = false;

  try
  {
   S.Bind(serverEP);
   S.Listen(1000);
   isListening = true;

   /*
    * While statement not required here because AcceptConnection()
    * method instructs the socket to BeginAccept() again...
    */
   //while (true)
   //{
   connectDone.Reset();
   S.BeginAccept(new AsyncCallback(AcceptConnection), Channel);
   connectDone.WaitOne();
   //}
  }
  catch (System.Net.Sockets.SocketException SockEx)
  {
   Console.WriteLine("*****[" + name + "] " + SockEx.SocketErrorCode + ":");
   Console.WriteLine("*****[" + name + "] " + SockEx.Message);
  }
 }
}

Из-за асинхронных методов вещи на самом деле не «заканчиваются» и возвращают сигнал для продолжения чего-либо еще. Любые команды, которые я реализую после Thread.Start () выше, не работают должным образом. Например, в StartListen, обратите внимание, что у меня есть isListening = true. После запуска потока я хочу использовать свойство IsListening. Он всегда возвращается как ложный.

Как мне начинать тему? Будет ли предпочтительным асинхронный метод (т.е. ThreadStart.BeginInvoke ())? Разве это не похоже на использование ManualResetEvent?

1 Ответ

2 голосов
/ 17 ноября 2009

Пометить isListening как volatile. Насколько я понимаю, вы ссылаетесь на этот флаг в двух разных потоках. Обычно данные, совместно используемые потоками, должны быть синхронизированы, но, похоже, вы этого не делаете. Однако, учитывая, что флаг является типом bool, технически вам не нужно синхронизировать доступ к нему, потому что .NET Framework гарантирует, что чтение и запись из типов bool являются атомарными (я думаю Я говорю это правильно ... кто-то, пожалуйста, поправьте меня, если это не технически правильно). Но, чтобы убедиться, что чтения из этого типа действительно получают самое последнее значение, вам нужно пометить его как volatile.

Кроме того, вам лучше использовать класс TcpListener вместо попыток сделать это с классом Socket. То, что вы делаете, не является неправильным, но класс TcpListener сделает ваш код проще для чтения и обслуживания, IMO.

Наконец, используемый вами объект locker на самом деле ничего не делает, поскольку он является локальным для метода StartListen(). Чтобы объекты синхронизации имели какой-либо эффект, они должны быть доступны для потоков, которым требуется сериализованный доступ к общим данным. Как вы делаете здесь, другие потоки не могут получить доступ к переменной locker, что делает ее бесполезной.

...