I have very similar code when using the standard BeginRead and EndRead methods from the TcpClient and using Task.Factory.FromAsync.
Here are some examples.. Error handling code not shown.
Task.Factory.FromAsync:
private void Read(State state)
{
Task<int> read = Task<int>.Factory.FromAsync(state.Stream.BeginRead, state.Stream.EndRead, state.Bytes, state.BytesRead, state.Bytes.Length - state.BytesRead, state, TaskCreationOptions.AttachedToParent);
read.ContinueWith(FinishRead);
}
private void FinishRead(Task<int> read)
{
State state = (State)read.AsyncState;
state.BytesRead += read.Result;
}
Standard use of callbacks with BeginRead and EndRead:
private void Read(State state)
{
client.BeginRead(state.Bytes, state.BytesRead, state.Bytes.Length - state.Bytes.Read, FinishRead, state);
}
private void FinishRead(IAsyncResult async)
{
State state = (State)async.AsyncState;
state.BytesRead += state.Stream.EndRead(async);
}
Both of these work fine but I am curious of their differences. The lines of code for both are pretty much equivalent and they both seem to perform the exact same function and have the same efficiency. Which one is preferable? What would you rather see in production code?
I would much rather see
Task<T>
based code:Task<T>
tasks and returns another task which represents the majority verdict of those tasks. Likewise you can wait until any one of a collection of tasks has completed, etc.IAsyncResult
type returned byBeginRead
.Task<T>
is getting better language support in C# 5 with async/await - if your codebase already usesTask<T>
pervasively, it'll be much easier to take advantage of thisBasically in modern code running on .NET 4,
Task<T>
is the idiomatic way of representing an on-going task. It's a much richer environment to work in than earlier attempts, and I would embrace it if you have the chance. Obviously if you're using .NET 3.5 or earlier, life is a bit harder, but I'm assuming that as you're asking the question,Task<T>
is an option...