I am attempting to speed up the processing of 5000 rows received from the database, which I then render as a crystal report, export to a byte stream and save in a database table.
Currently I am using parallel.ForEach
on a datatable. This uses 40 parallel processes that then sequentially iterates 125 (i.e 5000/40) records each of the 5000 rows.
It take approximately 5 minutes to do 5000 records at the moment. Is there any way I can speed this up?
DataTable dtBills = new DataTable("dtBills");//I used an OdbcDataAdapter to fill this with 5000 records
private void ParallelProcess()
{
int numbills = 5000;
int numprocesses = 40;
int numsequential = numbills / numprocesses;
int p=0;
if (numbills < numprocesses)
p = numbills;
else
p = numprocesses;
Parallel.For(1, p+1, new ParallelOptions { MaxDegreeOfParallelism = 40 }, i =>
{
SequentialProcess(numsequential,i);
});
}
private void SequentialProcess(int batch,int num)
{
ReportDocument cryRpt = new ReportDocument();
cryRpt.Load(Application.StartupPath + "\\" + "Bill.rpt");
foreach(DataRow drow in dtBills.Rows.Cast<System.Data.DataRow>().Skip((num - 1) * batch).Take(batch).CopyToDataTable().Rows)
{
cryRpt.SetParameterValue(..... //here I set Crystal report Parameter values
Stream stream = cryRpt.ExportToStream(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat);
byte[] contents = new byte[stream.Length];
stream.Read(contents, 0, (int)stream.Length);
stream.Close();
if (!string.IsNullOrEmpty(sconnstr))
{
using (SqlConnection sconn = new SqlConnection(sconnstr))
{
String qry = @"INSERT INTO ....."
using (SqlCommand cmd = new SqlCommand(qry, sconn))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue(// Set values for insert here one of which will be contents
cmd.Connection = sconn;
sconn.Open();
cmd.ExecuteNonQuery();
sconn.Close();
}
}
}
}
cryRpt.Close();
cryRpt.Dispose();
}
Parallel.For
might not useMaxDegreeOfParallelism
threads, but it will always perform allp
iterations. – svick Nov 29 '14 at 19:12