2011-10-22 34 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; 
...