I am trying to measure improvement in amount of time if I use Http Async instead of Sync one, but the code below deadlocks because of Async method contexts I searched and found one can use ConfigureAwait(false) to fix the situation but the code still deadlocks. Any suggestions on how I can fix this?
class Program
{
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
var entities = new List<string>() { "iron+man+3", "dark+knight+rises", "frozen+movie" };
stopwatch.Start();
int taskStatus = AsyncGet(entities).Result;
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedTicks);
stopwatch.Reset();
stopwatch.Start();
SyncGet(entities);
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedTicks);
var depTime = DateTime.UtcNow;
depTime = depTime.AddMilliseconds(-depTime.Millisecond);
Console.WriteLine(depTime.ToString("yyyy-MM-ddTHH:mm:ss.fff"));
Console.Read();
}
private static async Task<int> AsyncGet(List<string> entities)
{
var taskHttpList = new List<Task<WebResponse>>();
var taskStreamList = new List<Task<string>>();
var uriTemplate = "https://www.google.co.in/?#q={0}";
foreach (var entity in entities)
{
Uri uri = new Uri(string.Format(uriTemplate, entity));
var request = WebRequest.Create(uri);
taskHttpList.Add(request.GetResponseAsync());
}
foreach (var task1 in taskHttpList)
{
var response = (HttpWebResponse)await task1.ConfigureAwait(false);
taskStreamList.Add((new StreamReader(response.GetResponseStream())).ReadToEndAsync());
}
foreach (var task in taskStreamList)
{
var responseStr = (String)await task.ConfigureAwait(false);
}
return 0;
}
private static void SyncGet(List<string> entities)
{
var uriTemplate = "https://www.google.co.in/?#q={0}";
foreach (var entity in entities)
{
Uri uri = new Uri(string.Format(uriTemplate, entity));
var request = WebRequest.Create(uri);
var response = request.GetResponse();
var str = new StreamReader(response.GetResponseStream()).ReadToEnd();
}
}
}
I imagine that there is a limit on the number of threads handling IO completion events. Instead of processing it in the lockstep fashion build a complete chain of tasks per work item:
private static async Task<int> AsyncGet(List<string> entities)
{
var tasks = new List<Task<string>>();
foreach (var entity in entities)
{
var t = AsyncGetResponse(entity);
tasks.Add(t);
}
await Task.WaitAll(tasks.ToArray()).ConfigureAwait(false);
return 0
}
static async Task<string> AsyncGetResponse(string entity)
{
const string uriTemplate = "https://www.google.co.in/?#q={0}";
Uri uri = new Uri(string.Format(uriTemplate, entity));
var request = WebRequest.Create(uri);
string result;
using (var response = (HttpWebResponse)await request.GetResponseAsync().ConfigureAwait(false))
{
var reader = new StreamReader(response.GetResponseStream()))
result = await (string) reader.ReadToEndAsync().ConfigureAwait(false);
}
return result;
}
As was mentioned in comments, don't forget to dispose allocated resources, such as WebResponse.
Related
I am learning C# and I started to learn about things like asynchronous programming, streams and sockets so I tried to experiment with those concepts and made a simple program which is technically two programs with one server side and one client side. the server side is waiting for incoming connection and the client connect to the server and then both client and server can send text to each other and the text will be visible on the other side.
server side:
class Program
{
static void Main(string[] args)
{
var client = Conection();
while (true)
{
var task1 = Read(client.Result);
var task2 = Write(client.Result);
while (!task1.IsCompleted && !task2.IsCompleted)
{
}
}
}
async static Task<TcpClient> Conection()
{
var ip = IPAddress.Parse("127.0.0.1");
var port = 23000;
TcpListener server = new TcpListener(ip, port);
server.Start();
var client = await server.AcceptTcpClientAsync();
return client;
}
async static Task Read(TcpClient cli)
{
var stream = cli.GetStream();
var reader = new StreamReader(stream);
char[] buff = new char[64];
await reader.ReadAsync(buff, 0, buff.Length);
string text = new string(buff);
Console.WriteLine(text);
}
async static Task Write(TcpClient cli)
{
var stream = cli.GetStream();
var writer = new StreamWriter(stream);
var message = await Task.Run(() => Console.ReadLine());
writer.WriteLine(message);
writer.Flush();
}
}
client side:
class Program
{
static void Main(string[] args)
{
IPAddress ip = IPAddress.Parse("127.0.0.1");
var client = new TcpClient();
client.Connect(ip, 23000);
var stream = client.GetStream();
var reader = new StreamReader(stream);
var writer = new StreamWriter(stream);
while (true)
{
var task1 = Read(reader);
var task2 = Write(writer);
while(!task1.IsCompleted && !task2.IsCompleted)
{
}
}
}
async static Task Write(StreamWriter wr)
{
var str = await Task.Run(() => Console.ReadLine());
wr.Write(str);
wr.Flush();
}
async static Task Read(StreamReader reader)
{
var str = await reader.ReadLineAsync();
Console.WriteLine(str);
}
}
It works fine but something looks wrong when I check in the task manager, it looks like in the client side the RAM usage is constantly rising without stopping just after sending some short text from the client or server side and the CPU usage is more than 11% in both the client and the server side...
Can I make this code more efficient in terms of using RAM and CPU?, or I simply did it all in the wrong way?.
This is a bad sign:
while(!task1.IsCompleted && !task2.IsCompleted)
You have designed your own spin wait, that takes up a whole core in a never-ending loop waiting for keyboard input. It's hard to see what you want to achieve here. However this would be a more sane approach:
static async Task Main(string[] args)
{
var ip = IPAddress.Parse("127.0.0.1");
var client = new TcpClient();
await client.ConnectAsync(ip, 23000);
var stream = client.GetStream();
var reader = new StreamReader(stream);
var writer = new StreamWriter(stream);
while (true)
{
await ReadAsync(reader);
await WriteAsync(writer);
}
}
private static async Task WriteAsync(StreamWriter wr)
{
var str = Console.ReadLine();
await wr.WriteAsync(str);
await wr.FlushAsync();
}
private static async Task ReadAsync(StreamReader reader)
{
var str = await reader.ReadLineAsync();
Console.WriteLine(str);
}
If you wanted to read from the stream asynchronously, you might try something like this
static async Task Main(string[] args)
{
var ip = IPAddress.Parse("127.0.0.1");
var client = new TcpClient();
await client.ConnectAsync(ip, 23000);
var stream = client.GetStream();
using var reader = new StreamReader(stream);
await using var writer = new StreamWriter(stream);
using var cs = new CancellationTokenSource();
var readTask = ReadAsync(reader,cs.Token);
while (!cs.Token.IsCancellationRequested)
{
var str = Console.ReadLine();
if (string.IsNullOrWhiteSpace(str))
{
cs.Cancel();
}
await writer.WriteAsync(str);
await writer.FlushAsync();
}
await readTask;
Console.WriteLine("Finished");
}
private static async Task ReadAsync(TextReader sr, CancellationToken token)
{
while (!token.IsCancellationRequested)
{
var str = await sr.ReadLineAsync();
Console.WriteLine(str);
}
}
.net 7.3 compliant
private static async Task Main(string[] args)
{
var ip = IPAddress.Parse("127.0.0.1");
var client = new TcpClient();
await client.ConnectAsync(ip, 23000);
var stream = client.GetStream();
using (var reader = new StreamReader(stream))
using (var writer = new StreamWriter(stream))
using (var cs = new CancellationTokenSource())
{
// starts a task hot, does not await
var readTask = ReadAsync(reader, cs.Token);
// goes in to a loop
while (!cs.Token.IsCancellationRequested)
{
var str = Console.ReadLine();
if (string.IsNullOrWhiteSpace(str))
{
cs.Cancel();
}
await writer.WriteAsync(str);
await writer.FlushAsync();
}
await readTask;
Console.WriteLine("Finished");
}
}
private static async Task ReadAsync(TextReader sr, CancellationToken token)
{
// read loop
while (!token.IsCancellationRequested)
{
var str = await sr.ReadLineAsync();
Console.WriteLine(str);
}
}
Your while loops look very concerning. 'While(statement){}' will cause your code to check the 'statement' as fast as your CPU is capable of checking it repeatedly until it finally changes. That's most likely what's causing your strange behaviour. If you want to have that sort of logic, it can help to have a delay between each check -
while (!task1.IsCompleted && !task2.IsCompleted)
{
await Task.Delay(100);
}
Doing something like that would solve your problem, except it's still terrible coding, because you're using a while loop when Async Tasks have inbuilt waiting methods.
You could use .Wait() instead to bipass the entire loop, which would be an OK solution
while (true)
{
var task1 = Read(reader);
var task2 = Write(writer);
task1.Wait();
task2.Wait();
}
My preferred solution however, would be to make main an async method and to await task1 and task2
while (true)
{
var task1 = Read(reader);
var task2 = Write(writer);
await task1;
await task2;
}
or if main can't be async then to put all of the code in Main into a second method (that is async) and then within main you would just call your second method with a .wait statement
Implementation #1 - using Parallel loop
var client = new HttpClient();
var processes = new List<Task<object>>();
Parallel.ForEach(urls, url =>
{
processes.Add(client.GetAsync(url).Result.Content.ReadAsAsync<object>());
});
Task.WhenAll(processes);
Implementation #2 - using async method + Result
var client = new HttpClient();
var processes = new List<Task<object>>();
urls.ForEach(url =>
{
processes.Add(GetChain(client, url));
});
Task.WhenAll(processes);
async Task<object> GetChain(HttpClient client, string url)
{
return await client.GetAsync(url).Result.Content.ReadAsAsync<object>();
}
Implementation #3 - using async method + await
var client = new HttpClient();
var processes = new List<Task<object>>();
urls.ForEach(url =>
{
processes.Add(GetChain(client, url));
});
Task.WhenAll(processes);
async Task<object> GetChain(HttpClient client, string url)
{
var chain = await client.GetAsync(url);
return await chain.Content.ReadAsAsync<object>();
}
I like implementation #1 with Parallel loop, but there is a possibility that Parallel will create a new thread on each iteration and will consume more resources.
Questions
Is there a difference between these methods, can I keep using Parallel.ForEach?
If Parallel loop is bad, how can I improve it without creating a separate "async" method?
Is "await method.Result" the same as "await method1 await method2", #2 vs #3?
P.S. There are two "await" calls because HttpClient requests data, then read it asynchronously.
Extra question - are these lines the same?
method1.Result.method2 // get result immediately
method1.ContinueWith(data => data.Result.method2) // call both methods first
consider the following example . it helps your to find answer on your question:
private static readonly List<Uri> Urls = new List<Uri>() {
new Uri(""),
new Uri("") };
....
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var result1 = Urls.Select(GetContent).ToArray();
stopwatch.Stop();
Console.WriteLine($#"Synchronous and NOT In Parallel:{stopwatch.ElapsedMilliseconds}");
stopwatch.Restart();
var result2 = Urls.AsParallel().Select(GetContent).ToArray();
stopwatch.Stop();
Console.WriteLine($#"Synchronous and In Parallel:{stopwatch.ElapsedMilliseconds}");
stopwatch.Restart();
var task1 = DoAsyncNotParallel();
task1.Wait();
stopwatch.Stop();
Console.WriteLine($#"Asynchronous and NOT In Parallel:{stopwatch.ElapsedMilliseconds}");
stopwatch.Restart();
var task2 = DoAsyncInParallel();
task2.Wait();
stopwatch.Stop();
Console.WriteLine($#"Asynchronous and In Parallel:{stopwatch.ElapsedMilliseconds}");
static async Task<string[]> DoAsyncNotParallel()
{
List<string> content = new List<string>();
foreach (var uri in Urls)
{
content.Add(await GetContentAsync(uri));
}
return content.ToArray();
}
static async Task<string[]> DoAsyncInParallel()
{
var tasks = Urls.Select(uri => GetContentAsync(uri));
var content = await Task.WhenAll(tasks);
return content;
}
private static async Task<string> GetContentAsync(Uri uri)
{
HttpClient httpClient = new HttpClient();
var response = await httpClient.GetAsync(uri);
var content = await response.Content.ReadAsStringAsync();
return content;
}
private static string GetContent(Uri uri)
{
HttpClient httpClient = new HttpClient();
var response = httpClient.GetAsync(uri).Result;
var content = response.Content.ReadAsStringAsync().Result;
return content;
}
i recommend you to look through the following links which can be useful for you :
Async Programming : Introduction to Async/Await on ASP.NET, by Stephen Cleary
How and Where Concurrent Asynchronous I/O with ASP.NET Web API, by Tugberk Ugurlu
Parallel Programming with .NET, from Microsoft
about last part of question:
method1.Result.method2();
calling thread is blocked until method1 is completed, then method2 is being called
method1.ContinueWith(data => data.Result.method2());
calling thread is not blocked, method1 is being executed asynchronously .
once method1 is completed, then new Task is running like Task.Run(()=>{ method1.Result.method2()}). in this case method1.Result doesn't block calling thread because method1 alread completed, isCompleted=true
I am running into a deadlock situation when trying to post to WebApi 2 from WebApi 1 using HttpClient PostAsync and using async and await.
Below is WebAPI 1:
public HttpResponseMessage Get([FromUri]int oid)
{
var orderdetails = _orderServices.GetOrderDetails(oid);
var xml = new XmlMediaTypeFormatter();
xml.UseXmlSerializer = true;
string orderdetailsser = Serialize(xml, orderdetails);
var result = PostXml(orderdetailsser);
return Request.CreateResponse(HttpStatusCode.OK);
}
public static async Task<HttpResponseMessage> PostXml(string str)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:58285/");
var content = new StringContent(str);
var response = await client.PostAsync("api/default/ReceiveXml", content).ConfigureAwait(false);
return response;
}
}
And WebApi2:
[System.Web.Http.HttpPost]
public HttpResponseMessage ReceiveXml(HttpRequestMessage request)
{
var xmlDoc = new XmlDocument();
xmlDoc.Load(request.Content.ReadAsStreamAsync().Result);
xmlDoc.Save(#"C:\xmlfiles\xml2.xml");
XmlSerializer deserializer = new XmlSerializer(typeof(OrderInfoModel));
TextReader reader = new StreamReader(#"C:\xmlfiles\xml2.xml");
object obj = deserializer.Deserialize(reader);
OrderInfoModel orderdetails = (OrderInfoModel)obj;
reader.Close();
var patient_id = _patientServices.ProcessPatient(orderdetails.Patient, orderdetails.OrderInfo);
var orderid = _orderServices.ProcessOrder(orderdetails.Patient, orderdetails.OrderInfo, patient_id);
if (orderdetails.OrderNotes != null && orderdetails.OrderNotes.Count() > 0)
{
var success = _orderServices.ProcessOrderNotes(orderid, orderdetails.OrderNotes);
}
var prvid = _orderServices.ProcessOrderProvider(orderid, orderdetails.ReferringProvider);
var shpngid = _orderServices.ProcessOrderShipping(orderid, orderdetails.ShippingInfo);
var payerid = _orderServices.ProcessOrderPayer(orderid, orderdetails.Insurances);
return Request.CreateResponse(HttpStatusCode.OK, orderid);
}
I am not getting any response back to WebAPI 1 from WebAPI 2. I have gone through several articles online about deadlock situation. However, I am unable to resolve the deadlock in my case. What am I doing wrong here? Am I using async and await properly?
To build off my comment above, modify your code so that you are not blocking on an async operation. Additionally _orderServices.GetOrderDetails(oid); sounds like a method that hits a database and as such should be await _orderServices.GetOrderDetailsAsync(oid); wherein you use the whatever async api is available for your database access.
[HttpGet()]
public async Task<HttpResponseMessage> Get([FromUri]int oid) {
var orderdetails = _orderServices.GetOrderDetails(oid);
var xml = new XmlMediaTypeFormatter();
xml.UseXmlSerializer = true;
string orderdetailsser = Serialize(xml, orderdetails);
var result = await PostXml(orderdetailsser);
return Request.CreateResponse(HttpStatusCode.OK);
}
public static async Task<HttpResponseMessage> PostXml(string str) {
using(var client = new HttpClient()) {
client.BaseAddress = new Uri("http://localhost:58285/");
var content = new StringContent(str);
var response = await client.PostAsync("api/default/ReceiveXml", content).ConfigureAwait(false);
return response;
}
}
[HttpPost()]
public async Task<HttpResponseMessage> ReceiveXml(HttpRequestMessage request) {
var xmlDoc = new XmlDocument();
xmlDoc.Load(await request.Content.ReadAsStreamAsync());
xmlDoc.Save(#"C:\xmlfiles\xml2.xml");
XmlSerializer deserializer = new XmlSerializer(typeof(OrderInfoModel));
TextReader reader = new StreamReader(#"C:\xmlfiles\xml2.xml");
object obj = deserializer.Deserialize(reader);
OrderInfoModel orderdetails = (OrderInfoModel)obj;
reader.Close();
var patient_id = _patientServices.ProcessPatient(orderdetails.Patient, orderdetails.OrderInfo);
var orderid = _orderServices.ProcessOrder(orderdetails.Patient, orderdetails.OrderInfo, patient_id);
if(orderdetails.OrderNotes != null && orderdetails.OrderNotes.Count() > 0) {
var success = _orderServices.ProcessOrderNotes(orderid, orderdetails.OrderNotes);
}
var prvid = _orderServices.ProcessOrderProvider(orderid, orderdetails.ReferringProvider);
var shpngid = _orderServices.ProcessOrderShipping(orderid, orderdetails.ShippingInfo);
var payerid = _orderServices.ProcessOrderPayer(orderid, orderdetails.Insurances);
return Request.CreateResponse(HttpStatusCode.OK, orderid);
}
Resources
Don't Block on Async Code
Avoid Async Void
I'm trying to figure out the correct way to parallelize HTTP requests using Task and async/await. I'm using the HttpClient class which already has async methods for retrieving data. If I just call it in a foreach loop and await the response, only one request gets sent at a time (which makes sense because during the await, control is returning to our event loop, not to the next iteration of the foreach loop).
My wrapper around HttpClient looks as such
public sealed class RestClient
{
private readonly HttpClient client;
public RestClient(string baseUrl)
{
var baseUri = new Uri(baseUrl);
client = new HttpClient
{
BaseAddress = baseUri
};
}
public async Task<Stream> GetResponseStreamAsync(string uri)
{
var resp = await GetResponseAsync(uri);
return await resp.Content.ReadAsStreamAsync();
}
public async Task<HttpResponseMessage> GetResponseAsync(string uri)
{
var resp = await client.GetAsync(uri);
if (!resp.IsSuccessStatusCode)
{
// ...
}
return resp;
}
public async Task<T> GetResponseObjectAsync<T>(string uri)
{
using (var responseStream = await GetResponseStreamAsync(uri))
using (var sr = new StreamReader(responseStream))
using (var jr = new JsonTextReader(sr))
{
var serializer = new JsonSerializer {NullValueHandling = NullValueHandling.Ignore};
return serializer.Deserialize<T>(jr);
}
}
public async Task<string> GetResponseString(string uri)
{
using (var resp = await GetResponseStreamAsync(uri))
using (var sr = new StreamReader(resp))
{
return sr.ReadToEnd();
}
}
}
And the code invoked by our event loop is
public async void DoWork(Action<bool> onComplete)
{
try
{
var restClient = new RestClient("https://example.com");
var ids = await restClient.GetResponseObjectAsync<IdListResponse>("/ids").Ids;
Log.Info("Downloading {0:D} items", ids.Count);
using (var fs = new FileStream(#"C:\test.json", FileMode.Create, FileAccess.Write, FileShare.Read))
using (var sw = new StreamWriter(fs))
{
sw.Write("[");
var first = true;
var numCompleted = 0;
foreach (var id in ids)
{
Log.Info("Downloading item {0:D}, completed {1:D}", id, numCompleted);
numCompleted += 1;
try
{
var str = await restClient.GetResponseString($"/info/{id}");
if (!first)
{
sw.Write(",");
}
sw.Write(str);
first = false;
}
catch (HttpException e)
{
if (e.StatusCode == HttpStatusCode.Forbidden)
{
Log.Warn(e.ResponseMessage);
}
else
{
throw;
}
}
}
sw.Write("]");
}
onComplete(true);
}
catch (Exception e)
{
Log.Error(e);
onComplete(false);
}
}
I've tried a handful of different approaches involving Parallel.ForEach, Linq.AsParallel, and wrapping the entire contents of the loop in a Task.
The basic idea is to keep of track of all the asynchronous tasks, and awaiting them at once. The simplest way to do this is to extract the body of your foreach to a separate asynchronous method, and do something like this:
var tasks = ids.Select(i => DoWorkAsync(i));
await Task.WhenAll(tasks);
This way, the individual tasks are issued separately (still in sequence, but without waiting for the I/O to complete), and you await them all at the same time.
Do note that you will also need to do some configuration - HTTP is throttled by default to only allow two simultaneous connections to the same server.
I'm using an API to get data and store it in Database. The problem is that API return only 50 records per a call, so to get more data in less time, we have used Parallel.For in the application. The code which I'm using below is saving the data in database successfully most of the times but it's throwing an exception in rare cases. The exception which it's throwing at rare cases is
The tasks array included at least one null element. Parameter name: tasks | at System.Threading.Tasks.Task.WaitAll(Task[] tasks, Int32 millisecondsTimeout, CancellationToken cancellationToken) at System.Threading.Tasks.Task.WaitAll(Task[] tasks, Int32 millisecondsTimeout).
I don't know the reason of the exception because most of the time it is giving the correct results and I can save data in database. Below is the code which I have written. Please help me with resolving this issue, I'm new to the parallel programing.
object objobject = new object();
public void GetDataConcurrent()
{
var tasks = new List<Task>();
ParallelOptions objParallelOptions = new ParallelOptions();
CancellationTokenSource objCancellationTokenSource = new CancellationTokenSource();
objParallelOptions.MaxDegreeOfParallelism = 3;
objParallelOptions.CancellationToken = objCancellationTokenSource.Token;
string CompletePostData = "PostData to send to API";
string tException = string.Empty;
int noOfrequests = 15;
string jsonResponse=string.Empty;
try
{
Parallel.For(0, noOfrequests, objParallelOptions, (ChangeSetValue) =>
{
tasks.Add(Task.Factory.StartNew(() =>
{
var webRequest = WebRequest.Create("http://urlofAPI");
webRequest.ContentType = "application/json";
webRequest.Method = "POST";
webRequest.Proxy = WebRequest.DefaultWebProxy;
webRequest.Proxy.Credentials = CredentialCache.DefaultCredentials;
POSTDATA objPOSTDATA = new POSTDATA();
objPOSTDATA.CompletePostData = CompletePostData + ",'ChangeSetValue':'" + (ChangeSetValue) + "'}";
string json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(objPOSTDATA);
var datatoSend = Encoding.UTF8.GetBytes(json);
webRequest.GetRequestStream().Write(datatoSend, 0, datatoSend.Length);
webRequest.GetReponseAsync().ContinueWith(t =>
{
if (t.Exception == null)
{
using (var sr = new StreamReader(t.Result.GetResponseStream()))
{
lock (objobject)
{
string str = sr.ReadToEnd();
jsonResponse = jsonResponse + str;
jsonResponse = jsonResponse.Replace("<string xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/\">", string.Empty);
jsonResponse = jsonResponse.Replace("</string>", string.Empty);
jsonResponse = jsonResponse.Substring(1, jsonResponse.Length - 2);
SaveData();// Method to Save Data in Database by Deserializing the JSON Response
jsonResponse = string.Empty;
}
}
}
else
{
tException = t.Exception.InnerException.Message;
}
}).Wait();
}));
});
Task.WaitAll(tasks.ToArray());
}
catch (OperationCanceledException ex)
{
LogException(InsertLogInformation(ex.Message));
}
catch (AggregateException ex)
{
for (int j = 0; j < ex.InnerExceptions.Count; j++)
{
LogException(InsertLogInformation(ex.Message));
}
}
catch (Exception ex)
{
LogException(InsertLogInformation(ex.Message));
}
}
public void SaveData()
{
//Method to Save Data in DataBase
}
public static class WebRequestExtensions
{
public static Task<WebResponse> GetReponseAsync(this WebRequest request)
{
return Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
}
}
public class POSTDATA
{
public string CompletePostData { get; set; }
}
To expand on the comment by #ta.speot.is (as no-one seems to want to add an answer to this question). The issue is that you are adding to the tasks array inside the Parallel.For. List<T> is not thread safe so you should synchronise calls to List<T>.Add with a lock statement.
The other thing I am not sure about is why you are creating Tasks inside the Parallel.For. The Parallel.For will create tasks itself so you could probably do away with the tasks list entirely.