在我的c#应用程序中,在某些稀疏情况下,Thread.Start没有返回
我用c#编写了一个TCP服务器应用程序。应用程序侦听入站连接 在主侦听器线程中使用TcpListener.AcceptTcpClient()方法 接收到连接时,TcpListener.AcceptTcpClient()将取消阻止并返回TCPClient对象 接收到连接后,将创建一个新线程,并开始向新连接读写数据 新线程由以下代码启动在我的c#应用程序中,在某些稀疏情况下,Thread.Start没有返回,c#,multithreading,windows-7,tcp,C#,Multithreading,Windows 7,Tcp,我用c#编写了一个TCP服务器应用程序。应用程序侦听入站连接 在主侦听器线程中使用TcpListener.AcceptTcpClient()方法 接收到连接时,TcpListener.AcceptTcpClient()将取消阻止并返回TCPClient对象 接收到连接后,将创建一个新线程,并开始向新连接读写数据 新线程由以下代码启动 while(true) { TcpClient client = serverListener.AcceptTcpClient(); if (clien
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 stack explorer查看应用程序所有线程的堆栈),发现主侦听器线程卡在上面显示的代码部分的下一行
t.Start(); /// Problem happens here. The thread gets stuck here and doesn't move further
我做了很多研究,却找不到它发生的原因。此行为仅在windows 7系统中观察到
谁能帮我解决这个问题
正如罗布建议的那样
我在这里发布windbg(sos)显示的堆栈跟踪
不确定这是否能解决您的问题:
// 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);
}
//启动ThreadProc。请注意,在单处理器上,新的
//在主线程运行之前,线程不会获得任何处理器时间
//被抢占或放弃。取消对线程的注释。睡眠
//跟随t.Start()查看差异。
t、 Start();
//睡眠(0);
对于(int i=0;i<4;i++){
WriteLine(“主线程:做一些工作”);
睡眠(0);
}
资料来源:
解决问题的另一种方法可能是使用TCPListener async:我仍然没有找到上述问题发生的根本原因。然而,为了防止我的应用程序因这种情况而失败,我实施了以下变通方法 修改后的代码如下所示
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.start()上。在这种情况下,我将终止当前侦听器线程并启动新的侦听器线程。我想我已经解决了问题 我确实错误地关闭了另一个线程中打开的句柄。我通过pinvoke使用本机关闭方法在一个线程中关闭同一个句柄两次。在第一次关闭句柄之后,同一个句柄可能被分配到进程中的某些内部位置。在执行第二次关闭后,它实际上关闭了打开的句柄,因此导致该过程中无法解释的不适用性
删除第二次关闭后,问题不再出现。Thread.Start不太可能返回。更可能是你的检查或确定方法是错误的。是什么让你认为Thread.Start没有返回?通常不建议每个连接有一个线程;它不会扩展。您有多少个传入连接?在挂起时您有多少个活动客户端?-每个客户端的线程伸缩性并不总是很好。您是否可以直接确认此行为(没有附加调试程序,或者通过查看转储)?尝试在
t.Start()
之前和之后使用log语句或Console.WriteLine,写出线程管理的id或诸如此类的内容,然后确认您确实遇到了“before”消息而没有相应的“after”消息。@KierenJohnstone,如本文所述,我使用MicrosoftStackExplorer查看被卡住线程的堆栈。每次出现此问题时,它都表明主侦听器线程的状态正在运行,并且线程被卡在线程上。startIt仍然可以被抢占,因此这不会改变它的工作状态-它只会改变另一个线程显示的速度。我的问题是,我的主线程永久卡在thread.start上。我不认为可以通过强制抢占任何线程来解决这个问题。这只是额外的延迟。侦听器线程在循环返回时很快就会阻塞accept()调用-不需要任何sleep()内容;像这样连续两次被调用CloseHandle(句柄);关闭手柄(手柄);它创建了racing codition,scond close正在关闭分配给某些内部流程功能的句柄
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;
}