I'm sending 10 messages from a client to a server in a loop, and then responses back from the server to the client using TPL's FromAsync (targeting .NET 4.0)
After the last message is sent from the client, I'm trying to measure the total time taken until the final response is received. To do this, I call Task.WaitAll but I get an AggregateException who's inner exception says "A task was cancelled" for all the tasks. The server is receiving the requests.
Code:
private static double MeasureAsyncTPL(List<string> stringList)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
var tasks = new Task[stringList.Count];
for (int i = 0; i < stringList.Count; i++)
{
string source = stringList[i];
tasks[i] = SendMessageToServerAsync(source);
//SendMessageToServerAsync(source);
}
Task.WaitAll(tasks);
stopwatch.Stop();
return stopwatch.Elapsed.TotalMilliseconds;
}
static Task SendMessageToServerAsync(string message)
{
Task task;
var byteArray = MessageToByteArray(message, Encoding.UTF8);
using (var tcpClient = new TcpClient())
{
tcpClient.Connect("127.0.0.1", 5000);
using (var networkStream = tcpClient.GetStream())
{
task = Write(networkStream,byteArray,0);
Task continuation = task.ContinueWith(ant => Read(ant, networkStream), TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.AttachedToParent);
return continuation;
}
}
}
private static Task Write(NetworkStream stream, byte[] buffer, int offset)
{
return Task.Factory.FromAsync(stream.BeginWrite, stream.EndWrite, buffer, offset, buffer.Length, null);
}
private static Task Read(Task write, NetworkStream stream)
{
byte[] data = new byte[50];
return Task<int>.Factory.FromAsync(stream.BeginRead, stream.EndRead, data, 0, data.Length, null);
}
The exception is being picked up inside MeasureAsyncTPL on the line Task.WaitAll(tasks). How can I fix this exception?
Second question - is FromAsync inside my Read method guaranteed to return the entire message from the server? Or do I need to call it multiple times while keeping track of a the size of the byte array that the server sent?
networkStreambefore writing or reading. - Yacoub MassadNotOnFaultedoption, pointing to an exception in yourWritetask (as others have pointed, likely due to premature stream disposal). Fix that and you'll fix theTaskCanceledException. - Kirill ShlenskiyTaskContinuationOptions.AttachedToParentdoes absolutely nothing as your task is not scheduled inside another task - it's just a continuation and has no parent to attach to. - Kirill Shlenskiyusingblock without synchronously blocking, otherwise the element will get disposed and you'll end up with a race condition, like you're seeing now. - Yuval ItzchakovIDisposablebeing alive, not just continuations (i.e. you shouldn't return a task asynchronously reading from aStreaminside theusingblock regardless of whether it has a continuation or not). - Kirill Shlenskiy