1

我有一个简单的 Windows 服务,每天只运行一次。它在数据库中执行一些查询,生成适当的 html 内容(表格、div、...)并将其以电子邮件正文的形式发送给多个收件人。

电子邮件的正文是这样创建的:

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方法都几乎相同——它们在我的数据库中执行查询,在 HTMLTextWriter 的帮助下构建一个 HTML 表,然后将表作为字符串返回。

可以使用多线程或异步等待模式来改进此代码吗?有问题的代码是我将行附加到 StringBuilder 对象的位置。

编辑:我问这个问题是因为我以前从未使用过多线程,只是想知道它是否可能。此外,该程序现在运行得足够快。

4

3 回答 3

2

如果它只生成一件事,那么并行化很复杂,因为您需要考虑同步。当您可以执行任务并行化(并行完成的单独和隔离操作)时,并行化是一个更明显的候选者。您也没有提供足够的信息来表明是否需要进行复杂的工作:

  • 现在需要多长时间?
  • 需要那个时间是个问题吗?

如果有显着的好处(证明付出巨大努力的理由),那么当然!然而,我强烈怀疑答案是否定的,在这种情况下,别管它。在单个操作中处理多个线程很复杂。

您也许可以将单独的文档部分视为并行任务,但 HTML 生成通常非常快 - 所以除非您对此进行了分析并且知道它们需要时间,否则不要打扰。更有可能:您的数据查询是障碍。在这种情况下,花一些时间改进它,而不用担心并行化。

于 2011-10-22T11:39:57.687 回答
1

如果这些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;
...
于 2011-10-22T11:43:40.103 回答
0
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); }
);
于 2011-10-22T11:40:23.517 回答