在socket编程中出现ContextSwitchDeadlock的问题

wickey_lu 2007-05-14 08:37:38
我要实现一个简单的服务器,其中主要的一段代码如下:
public void ServerThreadProc()
{
try
{
clientSocket = serverSocket.Accept();

//接收客户端发来的数据
byte[] recvBytes = new byte[1024];
int bytes = 0;
bytes = clientSocket.Receive(recvBytes, 0, clientSocket.Available, SocketFlags.None);
string strRequest = System.Text.Encoding.Unicode.GetString(recvBytes, 0, bytes);

ProcessParams(strRequest); //从strRequest中提取必要的参数

c.ConvertF(a,b); //a,b是类的成员变量,已在ProcessParams(strRequest)中提取了正确的值,c 是一个类的对象,其类型为另一dll中的某个类,这里通过c来访问该类中的Convert函数,Convert中调用了word的一些编程api

clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
}
catch (Exception ex)
{
if (clientSocket.Connected)
{
clientSocket.Close();
}
}
现在遇到以下问题,上述的代码一直到执行完ProcessParams(strRequest)结果还是正确的.但执行到Convert函数中(注意Convert位于另一dll中)的调用Word编程api那一句时就出错了.出现了以下提示:
检测到 ContextSwitchDeadlock
Message: CLR 无法从 COM 上下文 0x196c58 转换为 COM 上下文 0x196ae8,这种状态已持续 60 秒。拥有目标上下文/单元的线程很有可能执行的是非泵式等待或者在不发送 Windows 消息的情况下处理一个运行时间非常长的操作。这种情况通常会影响到性能,甚至可能导致应用程序不响应或者使用的内存随时间不断累积。要避免此问题,所有单线程单元(STA)线程都应使用泵式等待基元(如 CoWaitForMultipleHandles),并在运行时间很长的操作过程中定期发送消息。

请不要告诉我要把调试->异常->Managed Debugging Assistant->ContextSwitchDeadlock的引发选项去掉,我试过了不是这个问题.也不要说把线程的ApartmentState设为ApartmentState.MTA,也不是这个原因导致的.
并且不要告诉我把c.ConvertF(a,b)的调用放在一个线程中,我也试过了,这样虽然可以,但由于此时会执行了clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();,搞到我不能向客户端发送执行的结果了.
我发现只有在clientSocket被close后,再执行ConvertF这个方法才会没有出错,但我必须在完成前不能关闭那个clientSocket,因为我还要把处理的结果发送会给客户端.请各位高手帮我解决一下这个问题.
...全文
530 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
james_hunter 2007-05-14
  • 打赏
  • 举报
回复
不知道。我又不知道你的c.Convert是怎么写的……
问题多半在这个里边。
wickey_lu 2007-05-14
  • 打赏
  • 举报
回复
试了一下,发觉只要是在
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close(); 执行前,调用ConvertF(不论是否放在独立进程中,都会出错),在那两句执行后才调用就没事.知道什么原因吗
james_hunter 2007-05-14
  • 打赏
  • 举报
回复
http://topic.csdn.net/t/20060302/14/4588245.html
这个帖子有说到怎么写等待线程结束的代码。你参考下
wickey_lu 2007-05-14
  • 打赏
  • 举报
回复
现在的问题是,把到放到另一个线程里面去执行的话,代码变为如下:
public void ServerThreadProc()
{
try
{
clientSocket = serverSocket.Accept();

//接收客户端发来的数据
byte[] recvBytes = new byte[1024];
int bytes = 0;
bytes = clientSocket.Receive(recvBytes, 0, clientSocket.Available, SocketFlags.None);
string strRequest = System.Text.Encoding.Unicode.GetString(recvBytes, 0, bytes);

ProcessParams(strRequest); //从strRequest中提取必要的参数

Thread thread=new Thread(new ThreadStart(ConvertF));
thread.Start();

clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
}
catch (Exception ex)
{
if (clientSocket.Connected)
{
clientSocket.Close();
}
}
}
这样的话,在线程还没执行完时,就已经执行了 clientSocket.ShutdownSocketShutdown.Both);
clientSocket.Close();
这样我还怎样把结果发送会客户端呢
james_hunter 2007-05-14
  • 打赏
  • 举报
回复
我就要告诉你,放到另外一个线程去执行c.ConvertF(a,b)!
你是不是就不给我分了?
这里原因编译器都说的很清楚了,
你可以在clientSocket.Shutdown(SocketShutdown.Both)前边,再添加一段等待线程结束的代码。
C++中可以用WaitSingleObject,C#里边用什么我还真不知道,你google一下。

110,499

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧