我正在实现一个基于TCP/IP的客户端协议MyProtocol。该协议的Connect()方法应该具有类似于TcpClient.ConnectAsync()的签名-也就是说,它应该返回一个Task:
Task MyProtocol.Connect (…);
这个方法(MyProtocol.Connect()
)应该通过异步TCP/IP连接(通过TcpClient.ConnectAsync()
),返回一个未完成的任务T,然后定期发送一条特定的消息M到服务器 - 再次异步(通过NetworkStream.WriteAsync()
)。当从服务器接收到某个响应R - 再次异步(通过NetworkStream.ReadAsync()
),MyProtocol.Connect()
应该完成任务T。
我正在做以下事情:
// Client of the protocol:
var task = myProtocol.Connect(); // asynchronous call, we don’t want to wait until connected
task.ContinueWith(t =>
{
// Connected – doing an OnConnected stuff
…
});
// MyProtocol.Connect() implementation:
public class MyProtocol
{
private Task connectTask;
public Task Connect(…)
{
var tcpIpConnectTask = mTcpIpProtocol.Connect(…);
tcpIpConnectTask.ContinueWith(t =>
{
connectTask = new Task();
}
return connectTask;
}
}
定期向服务器发送信息 M 显然需要通过一个定时器完成。一旦异步地从服务器收到响应 R,就必须将 connectTask 标记为已完成,但我不知道如何实现这一点。 严格来说,我已经成功标记了 connectTask 为已完成; 我用 TaskCompletionSource<bool> 对其进行了包装,并使用 TaskCompletionSource.SetResult(true)。 但是我想知道这是否是我需要完成任务的唯一方式,更别说是最好的方式了?我特别不喜欢 TaskCompletionSource<> 必须具有非 void 任务结果类型(我使用 bool),即没有非泛型版本。 在 TPL 出现之前,我们有自己类似的框架和方法 Task.NotifyCompleted(),因此我们可以在一个地方创建任务,在另一个地方标记任务已完成 - 所有这些都是异步完成的。但是我所读到的关于 TPL 中任务的所有内容似乎都意味着只有当任务的委托运行到最后一行时,任务才会完成…… 或者我错过了什么简单的东西吗?
tcpIpConnectTask
呢?一旦连接完成,它就已经完成了。此外,如果您使用的是 .net 4.5,您可以使用async/await
来简化使用。 - NeddySpaghettitcpIpConnectTask
本质上就是TcpClient.ConnectAsync()
的返回值。根据上文所述,MyProtocol 在 TCP/IP 上添加了自己的功能,因此它只能将tcpIpConnectTask
作为中间结果使用,不能将其返回给客户端,因为在 MyProtocol 看来,当tcpIpConnectTask
完成时连接并不完整。 - alexk