i am using an API to get data and store it in Database, the problem is, the 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 is am using below is saving the data in database successfully most of the times, but it is throwing an exception in rare cases, the exception which it is 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 dont know the cause 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 in resolving this issue, i am 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; }
}