我可以在新线程上调用ReportExecutionService吗?

时间:2015-09-17 06:35:53

标签: c# multithreading task backgroundworker threadpool

这是我第一次处理大型多线程项目,所以请耐心等待。我们正在编写一个窗口服务,它将在数据库表上循环,并根据找到的记录生成SSRS报告。我试图把它写成一个多线程系统。

// 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);
}

在ProcessReport()方法内部,我调用ReportExecutionService并生成SSRS报告。这是一项长期运行的任务,最多可能需要12个小时。这是选项1为我想要生成的每个REPORT打开新线程。我们将限制我们打开的线程数

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

问题:

  1. 这是调用Reporting Web Service的有效方式吗?
  2. 我对TASK,BackgroundWorker,Thread,ThreadPool等多线程的所有不同选项感到不知所措。有没有比我上面的更好的方法来实现我的目标?

1 个答案:

答案 0 :(得分:1)

  

我对多线程的所有不同选项感到不知所措   像TASK,BackgroundWorker,Thread,ThreadPool。有没有更好的办法   实现我的目标比我上面的目标?

我明白你的意思。有很多方法可以在.NET中进行多线程工作。如果您正在寻找 parallalism ,请务必检查Task Parallel Library,因为它提供了与ThreadPool相比的另一个抽象级别以及一般的线程使用。如果您正在寻找并发(这正是您需要的),请查看async-await并研究其工作原理。

  

这是调用Reporting Web Service的有效方法吗?

高效是一个广义的术语,取决于您从中查看的视角。基本上,不需要在多个线程中执行HTTP请求只是为了让您的应用程序保持响应。由于网络IO本质上是异步的,因此您可以公开自己的非阻塞异步方法。

例如,它可能如下所示:

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);
    }
}

现在ProcessReport也变成了异步方法:

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);
}

现在你可以这样称呼它:

public async Task ProcessAllReports()
{
   var reportTasks = reportList.Select(report => ProcessReportAsync(report));
   ExecutionInfo[] reports = await Task.WhenAll(reportTasks);
   // Do stuff with the reports.
}