I’m implementing a client protocol MyProtocol over TCP/IP. The protocol’s Connect() method should have a signature similar to that of TcpClient.ConnectAsync() – that is, it should return a Task:
Task MyProtocol.Connect (…);
This method (MyProtocol.Connect()
) should make asynchronous TCP/IP connection (via TcpClient.ConnectAsync()
), return a non-completed task T and then periodically send a certain message M to the server – again asynchronously (via NetworkStream.WriteAsync()
). When a certain response R is received from the server – again asynchronously (via NetworkStream.ReadAsync()
), MyProtocol.Connect()
should complete the task T.
I’m doing the following:
// 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;
}
}
Periodical sending of message M to the server obviously has to be done through a timer. Once the response R is received from the server asynchronously, connectTask
must be marked as completed, and I don’t see ways of doing that.
Well, strictly speaking, I have managed to mark connectTask
as completed; I’m wrapping it in TaskCompletionSource<bool>
and use TaskCompletionSource.SetResult(true)
.
However I’m wondering if this is the only, let alone the best way of accomplishing what I need? I especially don’t like the fact that TaskCompletionSource<>
has to have a non-void task result type (I used bool), i.e. there’s no non-generic version.
Until TPL arrived, we had our own similar framework and a method Task.NotifyCompleted()
, so we could create a Task in one place, and mark it as completed in another place – all this was working asynchronously. But all I’ve read about tasks in TPL seems to imply that a Task only completes if its delegate runs to the last line…
Or am I missing something simple?
tcpIpConnectTask
? That one is complete once the connection is complete. Also if you are using .net 4.5 you can useasync/await
which simplifies the usage – NeddySpaghettitcpIpConnectTask
is essentially whatTcpClient.ConnectAsync()
returns. As per above, MyProtocol adds its own functionality to TCP/IP, so it can only usetcpIpConnectTask
as an intermediate result, it can't return it to the client, because the connection won't be complete whentcpIpConnectTask
is complete, as far as MyProtocol is concerned. – alexk