我有一个场景,其中多个线程通过单个套接字发送数据。已将唯一标识符插入消息中,并在响应消息中回显唯一标识符。当套接字隔离到单个客户端时,一切都运行良好(如预期)。现在我正在寻找多个线程的异步/等待模式,其中客户机等待特定响应。
以下是一些代码示例:
上述示例在多线程情况下无法正常工作,因为消息可能以任何顺序返回,因此下一条从线路上返回的消息可能不属于当前客户端。我的想法是客户端将使用其唯一ID注册委托或任务(将其存储在字典中),并且当带有该唯一ID的消息返回时,委托或任务将使用响应字节“完成”。我猜这可以通过EventHandler相对容易地实现,但我正在寻找一种等待响应的方法。
例如:
我不知道"RegisterTask"方法看起来是什么样子,该如何存储任务,如何使任务'等待'并且后来将其作为任务结果'完成'。有什么想法吗?我已经研究了Toub的异步协作原语系列,但我不确定是否是正确的方法。
以下是一些代码示例:
using (var ns = new NetworkStream(_socket))
{
byte[] requestBuffer = GetBuffer(request);
await ns.WriteAsync(requestBuffer, 0, request.Length);
byte[] responseBuffer = await ReceiveMessageAsync(ns);
// process response message
}
上述示例在多线程情况下无法正常工作,因为消息可能以任何顺序返回,因此下一条从线路上返回的消息可能不属于当前客户端。我的想法是客户端将使用其唯一ID注册委托或任务(将其存储在字典中),并且当带有该唯一ID的消息返回时,委托或任务将使用响应字节“完成”。我猜这可以通过EventHandler相对容易地实现,但我正在寻找一种等待响应的方法。
例如:
using (var ns = new CustomNetworkStream(_socket))
{
Task waitTask = ns.RegisterTask(this.UniqueId);
byte[] requestBuffer = GetBuffer(request);
await ns.WriteAsync(requestBuffer, 0, request.Length);
byte[] responseBuffer = await waitTask;
// process response message
}
我不知道"RegisterTask"方法看起来是什么样子,该如何存储任务,如何使任务'等待'并且后来将其作为任务结果'完成'。有什么想法吗?我已经研究了Toub的异步协作原语系列,但我不确定是否是正确的方法。
TaskCompletionSource<T>
。但是,针对套接字通信,多线程异步 API 非常复杂,远比你的示例代码所展示的要复杂得多。我建议使用一个更高级的抽象,如 SignalR。 - Stephen Cleary