2011-10-22 35 views
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方法是几乎相同的 - 他们在我的数据库执行查询,建立一个HTML表的帮助HTMLTextWriter并以字符串形式返回表。

可以将此代码与多线程的使用改善或可能异步等待模式?有问题的代码是我将行追加到StringBuilder对象的地方。

编辑:我问这个问题,因为我从来没有与多线程工作过,只是想知道这是否是可能的。此外,该程序现在运行得足够快。

+0

是在循环中调用此方法的代码?即我猜你正在循环收件人列表并调用上面的代码来生成电子邮件,这是正确的吗?重构的 –

+0

第一步可以使用一个使用()大于2 的另一个问题是,你知道或认为这些方法GenerateHTMLContent是耗时的操作?首先,你有没有做过一些基准测试,以确定它们是否真的是最棒的? – Zenwalker

+1

非常不可能。线程有助于避免冻结用户界面(异步/等待)或在多核CPU上为您购买更多CPU周期。一天一次的程序不太可能具有用户界面。此代码需要更多的dbase服务器和网络带宽,而不是cpu周期。 –

回答

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

现在让我们假设我们希望文档部分以可预测的顺序出现:) –

+0

只有当slobodan不关心按什么顺序将这些部分添加到输出中时。 –

+0

然后将结果赋给不同的变量并以任何你想要的顺序在'Parallel.Invoke'后附加到'sb' –

2

如果只生成一个东西,你需要考虑同步并行化是复杂的。当您可以执行任务并行化(并行完成单独和孤立的操作)时,并行化是更明显的候选。您也没有提供足够的信息来指示是否需要复杂的工作:

  • 现在需要多长时间?
  • 这是一个需要花费时间的问题吗?

如果有一个显着的好处(证明大量的努力),那么肯定!不过,我强烈怀疑,答案是“否”,在这种情况下,请保持独立。在单个操作中处理多个线程非常复杂。

也许你可以考虑单独的文档部分的并行任务,但是HTML生成通常是相当快的 - 所以,除非你具有一定轮廓这一点,知道他们需要时间,不要打扰。更有可能:您的数据查询是封锁。在这种情况下,花点时间改进它,而不必担心并行化。

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; 
...