Можно ли улучшить этот код с помощью многопоточности? - PullRequest
1 голос
/ 22 октября 2011

У меня есть простой сервис Windows, который работает только один раз в день.Он выполняет некоторые запросы в базе данных, генерирует соответствующий HTML-контент (таблицы, div, ...) и отправляет его в теле письма нескольким получателям.

Тело письма создается следующим образомthis:

private static string GenerateBody()
{
    using (var stringWriter = new StringWriter())
    using (var htmlWriter = new HtmlTextWriter(stringWriter))
    {
        htmlWriter.RenderBeginTag("html");
        htmlWriter.RenderBeginTag(HtmlTextWriterTag.Head);
        htmlWriter.WriteLine("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />");
        htmlWriter.RenderEndTag();
        htmlWriter.RenderBeginTag("body");

        htmlWriter.Write(
            new StringBuilder()
                .Append(OverviewParagraph.GenerateHTMLContent())
                .Append(PackageWeightParagraph.GenerateHTMLContent())
                .Append(BoxWeightParagraph.GenerateHTMLContent())
                .Append(CodeQualityParagraph.GenerateHTMLContent())
                .Append(ChecksParagraph.GenerateHTMLContent())
                .ToString()
        );

        htmlWriter.RenderEndTag();
        htmlWriter.RenderEndTag();

        return stringWriter.ToString();
    }
}

Все методы GenerateHTMLContent практически одинаковы - они выполняют запрос в моей базе данных, создают таблицу HTML с помощью HTMLTextWriter и возвращают таблицу в виде строки.

Можно ли улучшить этот код с помощью многопоточности или, возможно, шаблона async-await?В рассматриваемом коде я добавляю строки к объекту StringBuilder.

РЕДАКТИРОВАТЬ: я задал вопрос, потому что раньше я никогда не работал с многопоточностью, просто хотел узнать, возможно ли это.Кроме того, теперь программа работает достаточно быстро.

Ответы [ 3 ]

2 голосов
/ 22 октября 2011

Если генерируется только одна вещь, распараллеливание является сложным, так как вам необходимо учитывать синхронизацию. Распараллеливание является более очевидным кандидатом, когда вы можете выполнить задачу распараллеливание (отдельные и изолированные операции выполняются параллельно). Вы также не предоставляете достаточно информации, чтобы указать, оправдана ли сложная работа:

  • сколько времени это займет сейчас?
  • это проблема, что это занимает время?

Если есть значительная выгода (для оправдания значительных усилий), тогда обязательно! Я, однако, сильно подозреваю, что ответ «нет», и в этом случае оставьте себя в покое. Обработка нескольких потоков в одной операции является сложной.

Возможно, вы могли бы рассматривать отдельные разделы документа как параллельные задачи, но генерация HTML обычно довольно быстрая - поэтому, если вы не профилировали это и не знаете, что на это требуется время, не беспокойтесь. Гораздо более вероятно: ваш запрос данных является блокировкой. В этом случае потратьте некоторое время на улучшение этого, не беспокоясь о распараллеливании.

1 голос
/ 22 октября 2011

Если методы GenerateHTMLContent изолированы (т.е. они не будут мешать друг другу при одновременном запуске), вы можете запустить их все вместе и собрать результаты, когда они станут доступны:

// start tasks
Task<string> overviewParagraph =
    Task.Factory.StartNew( () => OverviewParagraph.GenerateHTMLContent() );

Task<string> packageWeightParagraph =
    Task.Factory.StartNew( () => PackageWeightParagraph.GenerateHTMLContent() );

....

// collect results
string overviewParagraphHtml = overviewParagraph.Result;
string packageWeightParagraphHtml = packageWeightParagraph.Result;
...
0 голосов
/ 22 октября 2011
StringBuilder sb = new StringBuilder();
Parallel.Invoke(
    () => { var s = OverviewParagraph.GenerateHTMLContent(); lock (sb) sb.Append(s); },
    () => { var s = PackageWeightParagraph.GenerateHTMLContent(); lock (sb) sb.Append(s); },
    () => { var s = BoxWeightParagraph.GenerateHTMLContent(); lock (sb) sb.Append(s); },
    () => { var s = CodeQualityParagraph.GenerateHTMLContent(); lock (sb) sb.Append(s); },
    () => { var s = CodeQualityParagraph.GenerateHTMLContent(); lock (sb) sb.Append(s); }
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...