如何在 C# 中多线程执行长期任务

How to multithread long going task in C#

我有问题。我有应用程序,可以生成带有报告服务的 pdf。它工作正常,但需要大约 20-60 秒。生成一个pdf。这次是报告服务内部错误的结果。当我通过网络需要一个 pdf,或者一晚上需要 300 个 pdf 时,没关系,但现在我需要生成 7278 个文件。在一个线程中大约需要 4 天(大约 96 小时)。我需要让它在一晚(8-12 小时)内运行。我在考虑多线程。

关于代码。 Long 运行 任务(生成 pdf)在特殊的 Web 服务中生成,由控制台应用程序执行。控制台应用程序,首先获取客户端列表 (clientsId) 和报告结束日期。

代码:

        DateTime batchDate = new DateTime(year, month, 1).GetEndOfMonthDate();
        int[] clientsId = GetClientsIds(batchDate);

        SaveLogFile(batchDate);
        LogProcessingStart(clientsId);

        int successedCount = 0;
        int processingCount = 1;

        CreateReportsDirectoryIfNecessary(ReportDir);
        int i = 0;

        while (i < clientsId.Length)
        {
            try
            {
                logger.Trace(string.Format("Przetwarzanie klient_id = {0}. {1}/{2}", clientsId[i], processingCount, clientsId.Length));
                ExecuteRequest(batchDate, clientsId[i]);
                logger.Trace(string.Format("Koniec przetwarzania klient_id = {0}", clientsId[i]));
                successedCount++;
            }
            catch (SoapException ex)
            {
                logger.Trace(string.Format("Błąd przetwarzania klient id = {0}.", clientsId[i]));
                logger.Trace(string.Format("Szczegóły : {0}", ex.Actor));
            }
            catch (Exception ex)
            {
                logger.Trace("Błąd " + ex.Message);
            }

            i++;
            processingCount++;
            Thread.Sleep(TaskDelaySeconds * 1000);
        }


protected override void ExecuteRequest(DateTime batchDate, int clientId)
{
    bool success = false;

    for (int i = 0; i < 10 && success == false; i++)
    {
        try
        {
            var result = gateway.GetPlatformReport(clientId, batchDate);
            string reportPath = ReportDir + "/" + result.ReportName + ".pdf";
            File.WriteAllBytes(reportPath, result.Report);
            success = true;
        }
        catch (Exception ex)
        {
            string origAssemblyLocation = Assembly.GetExecutingAssembly().CodeBase;
            logger.Trace("Błąd generowania raportu. Szczegóły " + ex.Message);
            logger.Trace(string.Format("Próbuje jeszcze raz.. (Retry = {0})", i + 1));
        }
    }
}

长 运行 任务(生成 pdf)在执行 "gateway.GetPlatformReport(clientId, batchDate)" 的 ExecuteRequest(batchDate, clientsId[i]) 中生成(执行 Web 服务并需要 20-60 秒,每个客户端要求)。控制台应用程序和网络服务都在同一台机器上。

目前我有7278个客户,整个过程需要4天。

您可以尝试用并发 for 循环替换 while 循环。

Parallel.For(0, clientsId.Length, i =>
{
    // While body.
});

有关详细信息,请参阅:https://msdn.microsoft.com/en-us/library/Ff963552.aspx and https://msdn.microsoft.com/en-us/library/system.threading.tasks.parallel.for%28v=vs.110%29.aspx

看看Parallel.For。此构造类似于 for 循环,但会自动处理工作负载的分区和 运行 多个线程上的代码。

Parallel.For(0, clientsId.Length, i => ExecuteRequest(batchDate, clientsId[i]));

在客户端中使用 Parallel.For 对您没有帮助,除非 Web 服务可以同时处理多个请求。确保 Web 服务 运行 在多个线程上有多个请求,然后您可以按照其他人的建议在您的客户端中使用 Parallel.For。

也就是说,我会查看 PDF 生成代码。每个文件60秒很多,也许你可以加快速度。

更新:另一种选择 如果您的 Web 服务已经处理并发调用,则根本不需要更改客户端应用程序 - 只需 运行 控制台应用程序的多个实例,并为每个实例提供一组不同的项目。