2011-10-22 6 views
1

나는 간단한 Windows 서비스를 하루에 한 번만 실행합니다. 그것은 데이터베이스에서 몇 가지 쿼리를 수행하고 적절한 html 컨텐트 (테이블, divs ...)를 생성하고 여러 수신자에게 전자 메일 본문으로 보냅니다.멀티 스레딩을 사용하여이 코드를 향상시킬 수 있습니까?

전자 메일의 본문은 다음과 같이 작성됩니다

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 개 이상의 Using()를 사용하는 것일 수 있습니다. 다른 질문은 GenerateHTMLContent의 메소드가 시간 소모적 인 작업이라는 것을 알고 있습니까? 먼저 그들이 정말로 쇼 스트 스토퍼인지 아는 몇 가지 벤치마킹을 했습니까? – Zenwalker

+1

매우 드뭅니다. 스레드는 사용자 인터페이스 (async/await)가 멈추거나 멀티 코어 CPU에서 더 많은 CPU 사이클을 사는데 도움이됩니다. 하루 한 번 프로그램이 사용자 인터페이스를 가질 가능성은 거의 없습니다. 그리고이 코드는 cpu주기가 아닌 더 많은 dbase 서버와 네트워크 대역폭을 필요로합니다. –

답변

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; 
... 
관련 문제