1

This is my first time dealing with big multi threading project so please bear with me. We are writing a window service which will loop on the database table and generate SSRS reports based on records found. I am trying to write this as a multi thread system.

// THIS IS LONG RUNNING TASK
void ProcessReport(Report report)
{
      ReportExecutionService rs = new ReportExecutionService();
      rs.Credentials = new NetworkCredential(id,pass);
      rs.Url = "url...asmx";
      rs.ExecutionHeaderValue = new ExecutionHeader();
      rs.Timeout = Timeout.Infinite;
      string historyID = null;
      ExecutionInfo info = rs.LoadReport("/../ReportName", historyID);
}

Inside ProcessReport() Method, I make call to ReportExecutionService and generate the SSRS report. This is long running task, can take up to 12 hours. Here is option 1 to open new thread for each REPORT I want to generate. We shall limit the number of thread we open

foreach(Report report in reportList)
{
    if (report.ReportID != null)
    {
        Thread thread = new Thread(() => ProcessReport(report));
        thread.Start();
    }
}

Questions:

  1. Is this efficient way to call Reporting Web Service ?
  2. I am overwhelmed with all the different options of multi threading like TASK, BackgroundWorker, Thread, ThreadPool. Is there a better way to achieve my goal than what I have above ?
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
Zeus
  • 3,091
  • 6
  • 47
  • 60

1 Answers1

1

I am overwhelmed with all the different options of multi threading like TASK, BackgroundWorker, Thread, ThreadPool. Is there a better way to achieve my goal than what I have above ?

I definitely understand what you mean. There are many ways one can do multi-threaded work in .NET today. If you're looking for parallalism, definitely check the Task Parallel Library, as it provides another level of abstraction over the ThreadPool and use of threads in general. If you're looking for concurrency (which is exactly what you need here), look at async-await and study how it works.

Is this efficient way to call Reporting Web Service ?

Efficient is a broad term, and depends on the perspective you're looking at it from. Basically, there is no need to execute an HTTP request in multiple threads just to keep your app responsive. Because network IO is asynchronous by nature, you can expose your own asynchronous method which is non-blocking to do so.

For example, it could look like this:

public class ReportExecutionService
{
    private readonly HttpClient httpClient = new HttpClient();
    public async Task<ExecutionInfo> LoadReportAsync(string reportName, string historyId)
    {
        // Lets assume you're sending the report as a JSON, 
        // and the return type is also a JSON
        var content = new { ReportName = reportName, HistoryId = historyId };
        var response = await httpClient.PostAsJsonAsync(
                               $"http://www.apiaddress.com/{reportName}", content);
        var jsonResponse = await response.Content.ReadAsStringAsync();
        return JsonConvert.DeserializeObject<ExecutionInfo>(jsonResponse);
    }
}

Now ProcessReport turns into an asynchronous method as well:

public Task<ExecutionInfo> ProcessReportAsync(Report report)
{
    ReportExecutionService rs = new ReportExecutionService
    {
        Credentials = new NetworkCredential(id, pass),
        Url = "url...asmx",
        ExecutionHeaderValue = new ExecutionHeader(),
        Timeout = Timeout.Infinite
    };

    string historyID = null;
    return rs.LoadReportAsync("/../ReportName", historyID);
}

And now you can call it like this:

public async Task ProcessAllReports()
{
   var reportTasks = reportList.Select(report => ProcessReportAsync(report));
   ExecutionInfo[] reports = await Task.WhenAll(reportTasks);
   // Do stuff with the reports.
}
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
  • Hi, Thanks for the detailed info. I am planing to read up more on Tasks. In your example, I notice that you have Task.WhenAll() Does this line mean it will wait till all the tasks are finished. In my requirement I am not waiting for any callback....basically my service should just go execute reporting service and generate PDF or Excel files on the file disk. Your example is very simple but i do not yet understand how will TASK run all different report generation. Will they be running on different Threads and if so do I have access to those threads in run time, to get the status ? Thanks again – Zeus Sep 19 '15 at 04:07
  • 1
    They do not execute on different threads. Most of the work here is waiting on IO, and you don't need any threads for that. You can also process them as they finish one by one to create those PDF files you need. And yes, `Task.WhenAll` will wait for all of them to complete. – Yuval Itzchakov Sep 19 '15 at 06:48
  • I see, I have updated my implementation and it make sense however another thing I need to solve is report execution priority. If Certain reports has higher priority than they should be running with higher importance. I was going to use thread priority mechanism to solve this. how do I do that with Tasks and Async ? – Zeus Sep 23 '15 at 22:13
  • 1
    I suggest you'd ask a new question for that. – Yuval Itzchakov Sep 23 '15 at 23:25