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

Can I call ReportExecutionService on new Threads?

这是我第一次处理大型多线程项目,所以请多多包涵。我们正在编写一个 window 服务,它将在数据库 table 上循环并根据找到的记录生成 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,用于为我要生成的每个报告打开新线程。我们将限制我们打开的线程数

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

问题:

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

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 ?

我绝对明白你的意思。现在有很多方法可以在 .NET 中进行多线程工作。如果您正在寻找 parallalism,一定要检查 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 并研究它是如何工作的。

Is this efficient way to call 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.
}