Thread.Start не возвращается в некоторых редких случаях в моем приложении c # - PullRequest
2 голосов
/ 29 марта 2012

Я написал приложение на сервере TCP на c #.Приложение прослушивает входящие соединения

с использованием метода TcpListener.AcceptTcpClient () в основном потоке слушателя.

При получении соединения TcpListener.AcceptTcpClient () разблокирует и возвращает объект TCPClient.

При получении соединения создается новый поток, который начинает читать данные записи в новое соединение.

Новый поток запускается с помощью следующего кода.

while(true)
{
  TcpClient client = serverListener.AcceptTcpClient();


  if (client.Connected)
  {
    Thread t = new Thread(delegate() { readWriteData(client); });
    t.IsBackground = true;
    t.Start(); /// Problem happens here. The thread gets stuck here and doesn't move   further
  }
 }

Приложение работает нормальноно в некоторых случаях на машинах с Windows 7 приложение внезапно перестает прослушивать tcp-соединения.

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

 t.Start(); /// Problem happens here. The thread gets stuck here and doesn't move   further

Я провел много исследований и не мог найти, почему это происходит.Такое поведение наблюдается только в системах Windows 7.

Может кто-нибудь, пожалуйста, помогите мне решить эту проблему.

Как предложил Роб,

Я выкладываю здесь трассировку стека, показанную windbg (sos)

0547eae0 7282e006 mscorwks!Thread::StartThread+0xc3, calling mscorwks!_EH_epilog3
0547eb00 727ac825 mscorwks!__SwitchToThread+0xd, calling mscorwks!__DangerousSwitchToThread
0547eb10 728b9c6f mscorwks!ThreadNative::StartInner+0x1ba, calling mscorwks!__SwitchToThread
0547eb58 727e4b04 mscorwks!SafeHandle::DisposeNative+0x3a, calling mscorwks!LazyMachStateCaptureState
0547ebc8 728b9d80 mscorwks!ThreadNative::Start+0xa6, calling mscorwks!ThreadNative::StartInner
0547ec18 728b9d01 mscorwks!ThreadNative::Start+0x1f, calling mscorwks!LazyMachStateCaptureState
0547ec74 71de6afc (MethodDesc 0x71c13048 +0x8c System.Threading.Thread.Start()), calling mscorwks!ThreadNative::Start
0547ec8c 030e2a46 (MethodDesc 0x30da408 +0x25e WindowsService.Server.startListener()), calling (MethodDesc 0x71c13048 +0 System.Threading.Thread.Start())

Ответы [ 3 ]

1 голос
/ 05 апреля 2012

Тем не менее я не нашел причину, по которой вышеупомянутая проблема происходит.Однако, чтобы предотвратить сбой приложения из-за этой ситуации, я применил следующий обходной путь.

Модифицированный код, как показано ниже.

count = 0;

while(true)
{
  TcpClient client = serverListener.AcceptTcpClient();


  if (client.Connected)
  {
    Thread t = new Thread(delegate() { readWriteData(client); });
    t.IsBackground = true;

    ++count;
    t.Start(); /// Problem happens here. The thread gets stuck here and doesn't move   further
    ++count;
  }

}

Я проверяю в другом потоке, что если значение count не изменилось в течение 5 секунд, а значение count нечетное число, это означает, что поток слушателя застрял на t.Начните().В этом случае я прекращаю текущий поток слушателя и запускаю новый.

1 голос
/ 09 августа 2012

Думаю, я понял проблему.

Я по ошибке закрыл открытую ручку в другом потоке. Я закрывал один и тот же дескриптор два раза в потоке, используя собственный метод close через pinvoke. Может случиться так, что после первого закрытия дескриптора один и тот же дескриптор будет назначен некоторым внутри процесса. После того, как было выполнено второе закрытие, но он фактически закрыл открытую ручку, что привело к необъяснимой непригодности в процессе.

После удаления этого второго закрытия проблема больше не появлялась.

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

Не уверен, что это решит вашу проблему:

    // Start ThreadProc.  Note that on a uniprocessor, the new 
    // thread does not get any processor time until the main thread 
    // is preempted or yields.  Uncomment the Thread.Sleep that 
    // follows t.Start() to see the difference.
    t.Start();
    //Thread.Sleep(0);

    for (int i = 0; i < 4; i++) {
        Console.WriteLine("Main thread: Do some work.");
        Thread.Sleep(0);
    }

Источник: http://msdn.microsoft.com/en-us/library/system.threading.thread.aspx

Еще один способ обойти вашу проблему - использовать асинхронный TCPListener:
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.beginaccepttcpclient.aspx

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