user153923
user153923

Reputation:

Parallel.For - almost got this working

I have a collection of about 3500 product Serial Numbers that my software uses to create reports with about 10 times a week.

My code retrieves from a very flat database (think Excel spreadsheet) where it pulls 0 to 25+ records from a single table for each Serial Number. I pass this data to a static method that generates an instance of my CustomClass, and stores that in a collection to be passed back at the end of the routine.

This report typically takes about 20 minutes to run. A lot of that is limited by the data requests being sent to the old SQL 2000 Server, but the static class was written to alleviate as much string manipulations and data conversions as possible.

I want to write a Parallel.For to try and make this run even faster, but I can't figure out how to complete my routine.

Here is the simplified version of the routine I have now:

private CustomClass[] Test1(string[] serialNumbers) {
  List<CustomClass> list = new List<CustomClass>();
  for (int i = 0; i < serialNumber.Length; i++) {
    DataTable table = new DataTable();
    using (SqlCommand cmd = new SqlCommand("sp_GetData", m_open_conn)) {
      cmd.CommandType = CommandType.StoredProcedure;
      cmd.Parameters.Add("@sn", SqlDbType.Char, 20).Value = serialNumber[i];
      table.Load(cmd.ExecuteReader());
    }
    list.Add(CustomClass.CreateSummary(table));
  }
  return list.ToArray();
}

The task is to write the code above in a Parallel.For loop. All of the examples I have come across so far are overly simplistic, and do not give me any insight on how to convert my code.

Here is what I have so far, but the second 0 value (the one in my Action/Func statement) says Cannot implicitly convert type 'int' to 'jp2code.CustomClass' ...and I don't really understand enough to know what exactly I need to do to make this work.

private CustomClass[] Test1(string[] serialNumbers) {
  List<CustomClass> list = new List<CustomClass>();
  Parallel.For<CustomClass>(0, serialNumbers.Length, () => 0, (i, loop, list) => {
      DataTable table = new DataTable();
      using (SqlCommand cmd = new SqlCommand("sp_GetData", m_open_conn)) {
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add("@sn", SqlDbType.Char, 20).Value = serialNumber[i];
        table.Load(cmd.ExecuteReader());
      }
    }, (x) => list.Add(CustomClass.CreateSummary(table))
  );
  return list.ToArray();
}

Obviously, I am supposed to be initializing the array with something (not a 0), but I don't know what exactly to do here.

Could someone please help?

Upvotes: 0

Views: 216

Answers (2)

Davin Tryon
Davin Tryon

Reputation: 67336

I've found this blog a good resource for Parallel.For

To simply replace the for loop you should be able to do this:

private CustomClass[] Test1(string[] serialNumbers) {
  List<CustomClass> list = new List<CustomClass>();
  Parallel.For(0, serialNumber.Length, (i) => {
    DataTable table = new DataTable();
    using (SqlCommand cmd = new SqlCommand("sp_GetData", m_open_conn)) {
      cmd.CommandType = CommandType.StoredProcedure;
      cmd.Parameters.Add("@sn", SqlDbType.Char, 20).Value = serialNumber[i];
      table.Load(cmd.ExecuteReader());
    }
    list.Add(CustomClass.CreateSummary(table));
  });
  return list.ToArray();
}

Upvotes: 1

Asti
Asti

Reputation: 12687

Since you already have a fixed set of serial numbers, you really don't need Parallel.For.

You can use PLINQ.

return serialNumbers.AsParallel().Select(number => { ...get table... }).ToArray();

I wouldn't really recommend the ToArray() approach though.

Upvotes: 2

Related Questions