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

时间:2015-08-03 09:12:40

标签: c# multithreading parallel-processing task .net-4.5

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

关于代码。长时间运行的任务(生成pdf)在特殊的Web服务中生成,由控制台应用程序执行。控制台应用程序,首先获取客户端列表(clientsId)和raport endDate。

代码:

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

在执行“gateway.GetPlatformReport(clientId,batchDate)”的ExecuteRequest(batchDate,clientsId [i])中生成长时间运行的任务(生成pdf)(执行Web服务并按照客户端请求执行20-60秒) )。控制台应用程序和Web服务都在同一台机器上。

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

3 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:2)

除非Web服务可以同时处理多个请求,否则在客户端中使用Parallel.For将无法帮助您。确保Web服务在多个线程上运行多个请求,然后您可以像在其他人建议的那样在客户端中使用Parallel.For。

那就是说,我会查看PDF生成代码。每个文件60秒是非常多的,也许你可以加快它。

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

答案 2 :(得分:1)

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

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