2012-02-17 4 views
7

언제 TaskEx.Run을 사용해야하는지 이해하려고합니다. 아래에 쓴 두 개의 코드 샘플을 제공하여 동일한 결과를 산출합니다. 내가 뭘보고 실패하는 것은 내가 좋은 이유가 확신의 Task.RunExTaskEx.RunEx 접근 방식을 것이다 누군가가 나를 채울 수있는 희망 이유입니다.TaskEx.Run 대 TaskEx.RunEx를 사용하는 경우

async Task DoWork(CancellationToken cancelToken, IProgress<string> progress) 
{ 
    int i = 0; 
    TaskEx.RunEx(async() => 
     { 
      while (!cancelToken.IsCancellationRequested) 
      { 
       progress.Report(i++.ToString()); 
       await TaskEx.Delay(1, cancelToken); 
      } 
     }, cancelToken); 
} 
private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    if (button.Content.ToString() == "Start") 
    { 
     button.Content = "Stop"; 
     cts.Dispose(); 
     cts = new CancellationTokenSource(); 
     listBox.Items.Clear(); 
     IProgress<string> progress = new Progress<string>(s => 
     { 
      listBox.Items.Add(s); 
      listBox.ScrollIntoView(listBox.Items[listBox.Items.Count - 1]); 
     }); 
     DoWork(cts.Token, progress); 
    } 
    else 
    { 
     button.Content = "Start"; 
     cts.Cancel(); 
    } 
} 

내가 동일한 결과를 얻을 수 있습니다 like

async Task DoWork(CancellationToken cancelToken) 
    { 
     int i = 0; 
     while (!cancelToken.IsCancellationRequested) 
     { 
      listBox.Items.Add(i++); 
      listBox.ScrollIntoView(listBox.Items[listBox.Items.Count - 1]); 
      await TaskEx.Delay(100, cancelToken); 

     } 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     if (button.Content.ToString() == "Start") 
     { 
      button.Content = "Stop"; 
      cts.Dispose(); 
      cts = new CancellationTokenSource(); 
      listBox.Items.Clear(); 
      DoWork(cts.Token); 
     } 
     else 
     { 
      button.Content = "Start"; 
      cts.Cancel(); 
     } 
    } 
+0

위 스레드는 TaskEx.RunEx에 대한 설명으로 CTP의 핵심 .NET 기능에 포함될 수없는 변경 사항과 관련이 있지만 최종 릴리스에는 적절하게 통합됩니다. –

+0

변경된 작업 .RunEx' to'TaskEx.RunEx' 비동기 CTP'Task' 클래스에는'Run()'도'RunEx()'도 없습니다. 그들은 둘 다'TaskEx'에 있습니다. 내가 틀렸을 때 나를 바로 잡으십시오. –

답변

0

Task.Run은 대부분의 시나리오에서 새로운 스레드를 내가 이해함에 따라 생성합니다.

메서드를 async로 표시하고 awaiters를 사용하기 만하면 새 스레드가 생성되는 것은 아니며 호출 된 동일한 실행 스레드에서 완료된다는 것을 의미합니다. 많은 경우에.

여기 트릭은 SchedulingContext와 관련이 있습니다. 멀티 쓰레드 아파트먼트로 설정된 경우, 완료를 스레드 풀의 실행 가능한 스레드에 위임하게됩니다. 모든 WPF 및 WinForms UI 코드가 단일 스레드 아파트에있는 경우 코드에서 눈에 보이는 스레드 정렬없이 UI에서 직접 작업을 완료 할 수 있도록 호출 스레드로 돌아갑니다.

+0

'Task.Run'은 대개 새로운 스레드를 시작하지 않는 스레드 풀에 대기합니다. 'await'은 현재의'SynchronizationContext' 또는'TaskScheduler' (스레드가 아닌)에 대한 지속성을 계획합니다 - [이 기사]의 끝 부분을보십시오 (http://msdn.microsoft.com/en-us/magazine/gg598924.aspx) 여전히 CTP v3 (및 VS11 dev 미리보기)에서 적용됩니다. 또한 [내 비동기 소개] (http://nitoprograms.blogspot.com/2012/02/async-and-await.html)에서 비동기 컨텍스트를 다룹니다.이 컨텍스트는 MTA 또는 STA와 관련이 없지만 STA 또는 MTA를 지원하는 컨텍스트를 가질 수 있습니다. –

+0

나는 즐겁게 바로 잡았습니다 : D – Firoso

11

스레드 풀 컨텍스트에서 동기식 코드를 실행하려면 TaskEx.Run을 사용하십시오.

스레드 풀 컨텍스트에서 비동기 코드를 실행하려면 TaskEx.RunEx을 사용하십시오.

이것은 당신이 creating tasks 위해 가지고 여러 옵션 중 하나입니다 :

스티븐 Toub 행동의 차이와 관련이 블로그 게시물이 있습니다. Run/RunEx을 사용하지 않아도됩니다. 간단한 async 방법을 사용하고 백그라운드에서 무언가를 실행해야하는 경우에만 Run/RunEx을 사용하십시오.

+0

사실 그건 사실이 아닙니다 ... RunEx는 람다 식을 반환하는 값과 관련이 있습니다 ... 비동기 적이 아닙니다. 실행 비동기 람다 그냥 괜찮아요. – Firoso

+2

.Net 4.5 DP에서는'Task.Run()'만 있고, 'Ex'는 없습니다. – svick

+4

TaskEx는 CTP에만 있습니다. .Net 4.5에서는 TaskEx의 메소드가 Task에 통합되었습니다. – Phil

1

DoWork() 메서드의 차이점은 첫 번째 것 (TaskEx.RunEx() 사용)이 전혀 비동기 적이라는 것입니다. 완전히 동기식으로 실행하고 다른 스레드에서 다른 작업을 시작한 다음 완료된 Task을 즉시 반환합니다. 해당 작업에 await ed 또는 ed가있는 경우 이 내부 작업이 완료 될 때까지 대기하지 않습니다.

관련 문제