c# - 等待与请求序列号匹配的响应

标签 c# asynchronous async-await

我正在尝试实现一个网络应用协议(protocol)客户端库,由 TCP 连接上的二进制请求/响应组成,并且我希望该客户端完全异步,依赖于 c#5 的 async/await 结构。

在 NetworkStream 上发送的每个请求都包含一个关联的应用序列号。对请求的响应必须指定相同的序列号,以便响应可以与原始请求匹配。 当我发出请求R1时,对R1的响应当然可以在将来的任何时间到来,并且对其他请求的其他响应可能会在对R1的实际响应之前上线。

我想在库的客户端代码中做的事情就像简单愚蠢的事情

var resp = await SendSomeRequestAsync(req);

SendSomeRequestAsync 将在线上异步发送请求(正确理解该部分)并以某种方式等待关联的响应(与请求中发送的序列号匹配),例如(在 SendSomeRequestAsync 中)

var dummy = await _ns.WriteAsync(rawBytes, 0, rawBytes.Length); // _ns is a NetworkStream
var resp = await GetResponseMatchingSequenceNumberAsync(sequenceNumber);

我有一个循环,当客户端启动连接时启动,该循环异步读取连接上的传入响应:

 while (true)
 {
    Response rsp = await ReadNextResponseAsync(_ns);
    DispatchReceivedResponse(rsp);
 }

我不知道如何实现 GetResponseMatchingSequenceNumberAsync,或者我是否已经完全错误地执行了该操作。

希望我的问题足够清楚。

谢谢

最佳答案

我确实遇到了这个问题,并且以下内容看起来很干净:

创建 IDictionary<int,Response>并存储TaskCompletionSource<Response>其中的实例。当您收到响应时,找到 TaskCompletionSource 并将其设置为已完成。我不对这段代码的线程安全性做出任何声明。该字典可能应该是并发类型,或者至少在某种类型的锁中访问。

public Task<Response> GetResponseMatchingSequenceNumberAsync(sequenceNumber)
{
   var tcs=new TaskCompletionSource<Response>();
   pendingTasksDictionary.Add(sequenceNumber,tcs);
   return tcs.Task;
}

private void ResponseHandler(int sequenceNumber,Response response)
{
   var pendingTcs=pendingTasksDictionary[sequenceNumber];
   //remove from dictionary
   pendingTcs.SetCompleted(response);
}

关于c# - 等待与请求序列号匹配的响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11893624/

相关文章:

reactjs - 如何测试异步/等待 API 调用和更新 React 状态

c# - 实现会改变 await 的行为吗?

javascript - react native 异步存储不工作

c# - 这些默认参数的人造模拟之间是否存在显着的机械差异?

c# - TabIndex 无法正常工作

c# - 为什么我对 Kairos api 的 REST 请求说请求缺少必需的参数?

java - Servlet 3.0 async 支持的缺点

scala - 使用 Akka Streams、Scala 异步读取多个文件

c# - 为什么 1 000 000 不等于 1000000.toString ("N", new CultureInfo ("fr-FR"))

ios - 异步加载 UIView