c#:同步网络通信时出现死锁
本文关键字:死锁 网络通信 同步 | 更新日期: 2023-09-27 18:20:23
我想在c#中开发一个满足以下要求的网络库:
- 对两个方向的多个请求使用相同的连接
- 提供一种类似
response = Connection.Send(message);
的简单包装方法 - 支持SSL(这就是我不使用SocketAsyncEventArgs的原因)
基本上我有两个线程:
- First Thread(同步)侦听传入消息并分派所有内容
- 第二个线程负责请求处理
因此,基本上代码如下(非常简短):
BlockingCollection _receivingQueue;
ConcurrentDictionary <MessageID, ResponseHandlerDelegate> _responseHandlers;
Dictionary <MessageID, Message> _responses;
void ListeningThread()
{
while(true)
{
Message = ReadNetworkStream();
_receivingQueue.Add(Message);
}
}
void ProcessingThread()
{
if(Message == Request)
Dispatch(message);
if(Message == ResponseForARequest)
{
_responses.Add(Message.ID, Message);
_responseHandlers[Message.ID](Message);
}
}
这似乎效果不错。
然而,由于这是一个"易于使用"的库,我想开发上面提到的函数:Response = Connection.Send(Message)
基本上,我认为当新的响应到达时,我可以使用ManuelResetEvent进行通知:
Dictionary <Guid, ManualResetEvents> _resetters;
Message Send(Message)
{
ManualResetEvent mre = new ManuelResetEvent(false);
_resetters.Add(Message.ID, mre);
Connection.Send(Message);
WaitFor(mre);
return _responses[Message.ID];
}
MRE是根据注册的ResponseHandlerDelegate 设置的
ResponseArrived(Message)
{
_responses.Add(Message.ID, Message);
_resetters[Message.ID].Set();
}
只要没有并发的双向通信,这就可以工作。由于服务器端和客户端都使用相同的代码,它们都在等待MRE的设置。。。
请注意,上面的所有内容都是某种伪代码,因为真正的类太长了。如果您需要特定的代码部分,请告诉我。
那么我的问题是什么呢?
我觉得我制作的东西一团糟。有什么简单的方法可以解决这个问题吗?或者有人能告诉我如何以不同的方式实现这一点吗?
我不想使用WCF,以便更好地控制较低的层,主要是因为我想自己开发它:-)
感谢
为了在等待同步发送响应时防止阻塞或死锁,您需要一个发送线程PER请求。否则,Send B可以等待A的响应,A可以等待B的响应,两者都不会做任何事情(死锁),因为WaitFor是一个同步锁,它阻止调用Send方法的线程实际接收任何东西。
把它想象成一台状态机,由机器a和B运行你的库:
A --> send to B
B --> send to A
A --> wait for response
B --> wait for response
A --> receive message from B, but still waiting for B's response
B --> receive message from A, but still waiting for A's response
结果:
A --> has message from B but can't stop waiting to process it
B --> has message from A but can't stop waiting to process it
简而言之:您需要2个以上的线程。您需要N个线程,其中N是要同时执行的请求数,即使所有这些线程共享一个连接。使用内置或自制的线程池将有助于重用线程并降低垃圾收集成本。
每个请求旋转一个线程是可以的。。。事实上,这是令人鼓舞的。当单个线程也在等待响应时,不可能用单个线程充分处理多个请求。然而,如果你没有等待回应,这将是一个不同的故事。