Thread.Start is not returning in some sparse cases

2019-04-02 01:46发布

问题:

I have written a TCP server application in c#. Application listens for inbound connections

using TcpListener.AcceptTcpClient() method in main listener thread.

When a connection is received, TcpListener.AcceptTcpClient() unblocks and returns TCPClient object.

On receiving a connection, a new thread is created and started to read write data to new connection.

The new thread is started by following code.

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
  }
 }

The application runs fine but in some times in Windows 7 machines, the application suddenly stops listening for tcp connections.

On analysis of thread stacks of application in this state, ( Microsoft stack explorer was used to view stacks of all threads of the application ) it is found that the main listener thread is stuck on following line of the code section shown above

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

I did lot of research and couldn't find why it is happening. This behavior is observed only in windows 7 systems.

Can anybody please help me to solve this issue.

As suggested by Rob,

I am posting here stack trace shown by 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())

回答1:

Still I have not found the root cause why above mention problem is happening. However to prevent my application failing because of this situation I have implemented following workaround.

The modified code is as below.

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;
  }

}

I check in another thread that if value of count hasn't changed in 5 secs and the value of count is odd number that means the listener thread is stuck on t.start(). In that case, I terminate the current listener thread and start new one.



回答2:

I think I have figured out the issue.

I did close an open handle in another thread by mistake. I was closing same handle two times in a thread by using native close method via pinvoke. It might have happened that after first close of the handle, the same handle was assigned some where internal in process. After that second close was executed but it actually closed the open handle hence that led to unexplained unsuitability in the process.

After removing that second close, the issue didn't appear again.



回答3:

Not sure if that can solve your issue:

    // 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);
    }

Source: http://msdn.microsoft.com/en-us/library/system.threading.thread.aspx

Another way to work arround your issue might be to use the TCPListener async:
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.beginaccepttcpclient.aspx