我想在c#中开发一个满足以下要求的网络库:
response = Connection.Send(message);
基本上我有两个主题:
所以基本上代码如下(非常简短):
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,更好地控制较低层 - 主要是 - 因为我想自己开发它: - )
由于
答案 0 :(得分:1)
为了在等待同步发送的响应时防止阻塞或死锁,您需要发送线程PER请求。否则发送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是您要同时执行的请求数,即使所有这些线程共享一个连接。使用内置或自制的线程池可以帮助您重用线程并降低垃圾收集成本。
可以根据请求启动一个帖子......事实上,它是鼓励的。当单个线程也等待响应时,单个线程无法充分处理多个请求。但是,如果你不等待回应,那将是另一回事。