0

我需要的是一个按顺序执行异步操作的类。

class FooSocket
{
    private Socket _Socket;

    // Message is a class that wraps a byte array.
    public Task<Message> Receive() { /*Bla...*/ };
    public Task<int> Send(Message message) { /*Bla...*/ };
}

如果我按顺序调用发送、接收和发送,我需要先发送,并将剩余的接收和发送操作排队,直到第一个接收完成。

我尝试在课堂上创建一个主要任务领域并遵循MainTask = MainTask.ContinueWith(...)一种方法。我什至写了一个名为 Sequencer 的类,它正是这样做的,但不知何故感觉不对,在延续和其他东西中创建嵌套任务(使用 Task.Factory.FromAsync 方法)。

我还尝试做一些事情,比如排队 TaskCompletionSource 对象并在我的 Receive/Send 方法中返回它们的任务,在一个单独的线程上以无限循环检查队列,但由于我将拥有大约 200k 的 FooSocket 实例,每个线程也感觉失策。如果我把它变成一个线程池,我会得出这个“线程池不应该用于长时间运行的操作”的规则。

我感觉很接近,但不确定订购这些工作的最有效方式是什么。

4

2 回答 2

2

我会使用TPL Dataflow。您可以通过 NuGet或作为Async CTP的一部分安装它。TPL Dataflow 提供了一种BufferBlock<T>听起来正是您所需要的基本类型。

如果你只是建模一个套接字,那么Send当数据被缓冲出去时完成任务,不断地读入另一个缓冲区,Receive当你从那个缓冲区读取时完成任务。(注意:当数据缓冲到操作系统时,a 上的“发送”操作Socket完成,而不是当它通过线路输出或到达其目的地时)。

如果您正在建模更高级别的命令/响应,那么您应该有一个代表整个命令/响应的任务,正如 James 建议的那样。我会两者兼而有之;async使用/await支持很容易将一个层叠在另一个之上。(注意:a 上的“接收”操作Socket可能会以部分接收完成,因此您需要消息框架)。

您的架构可能还需要一些工作:

我将拥有大约 200k 的 FooSocket 实例

这肯定是个问题(我假设您使用的是 TCP/IP)。只有大约 65K TCP/IP 端口,默认情况下只有大约 16K 是短暂的,您必须为操作系统留出大量“喘息空间”,否则它会开始出现异常行为。我估计只有约 12K 的连接是现实的,除非您更改可以(理论上)使您达到约 59K 的短暂范围。大约 200K 是不可能的 - 除非您更改临时范围使用负载均衡器拥有多个 IP 地址。

于 2012-07-17T12:54:47.450 回答
1

如果它是请求/响应类型的行为,恕我直言,任务粒度应该是完整的往返,而不是分开发送和接收。

您不需要 CTP 来支持 .net 4,您可以使用异步目标包。

消费代码是什么样的?带有等待调用的循环?

于 2012-07-17T12:06:35.790 回答