2014-11-15 5 views
5

SynchronizationContext 및 async/await 메서드 (link)와 함께 사용하고 있습니다. 내 이해에서 SynchronizationContext가 null 인 콘솔 응용 프로그램에서 대기중인 메서드 (작업)의 연속은 ThreadPool이 될 기본 스케줄러로 예약됩니다.스레드 풀 스레드에서 작업 계속이 예약되지 않았습니다.

하지만이 콘솔 응용 프로그램을 실행하면, 당신은 계속 내가 만든 작업자 스레드에서 실행되는 출력에서 ​​볼 수 있습니다 : 여기

class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.WriteLine("MainThreadId=" + Thread.CurrentThread.ManagedThreadId); 
     Method1().ContinueWith(t => 
     { 
      Console.WriteLine("After Method1. ThreadId=" + Thread.CurrentThread.ManagedThreadId); 
     }); 

     Console.ReadKey(); 
    } 

    public static async Task Method1() 
    { 
     Console.WriteLine("Method1 => Entered. ThreadId=" + Thread.CurrentThread.ManagedThreadId); 

     TaskCompletionSource<bool> completionSource = new TaskCompletionSource<bool>(); 
     Thread thread = new Thread(() => 
     { 
      Console.WriteLine("Method1 => Started new thread. ThreadId=" + Thread.CurrentThread.ManagedThreadId); 
      Thread.Sleep(2000); 
      completionSource.SetResult(true); 
     }); 

     thread.Start(); 

     await completionSource.Task; 

     Console.WriteLine("Method1 => After WorkerThread. ThreadId=" + Thread.CurrentThread.ManagedThreadId); 
    } 
} 

그리고 출력입니다 :

MainThreadId=10 
Method1 => Entered. ThreadId=10 
Method1 => Started new thread. ThreadId=11 
Method1 => After WorkerThread. ThreadId=11 
After Method1. ThreadId=12 

당신이 볼 수 있듯이, "의 WorkerThread 후" 내 workerthread와 같은 스레드에서 출력되었지만 스레드 풀에서는 출력되지 않았습니다.

나는 question과 비슷한 것을 발견했지만 그 사람은 모노를 사용하고 있었으며 이것이 버그라고 말하고있었습니다. 필자는 Visual Studio에서이 코드를 작성하고 Windows 7 및 .NET 4.5.2를 내 컴퓨터에 설치하여 실행했습니다.

누군가가이 동작을 설명해 주시겠습니까?

답변

5

implementation detail that I documented on my blog : await에 의해 생성 된 연속은 ExecuteSynchronously 플래그를 사용하여 예약됩니다. 이 경우, 계속 작업을 시작할 시간이되면 (즉, 작업자 스레드의 TaskCompletionSource<T>.SetResult 호출에서) 기본 스케줄러는 먼저 현재 스레드에서 실행할 수 있는지 여부를 판별하려고 시도합니다.

Since the worker thread has no TaskScheduler that will reject executing the task synchronously, ExecuteSynchronously 플래그는 cause the thread pool task scheduler to just execute the task synchronously (즉, 호출 스레드에서)입니다.

+0

잡아! 따라서이 [article] (http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx?PageIndex=2#comments)은 "기다리는 작업이 완료되면 , 지속은 비동기 메서드의 나머지 부분을 실행합니다. 캡처 된 SynchronizationContext가 null이면 RestOfMethod()가 원래 TaskScheduler에서 실행됩니다 (TaskScheduler.Default, ThreadPool 의미). " – Absolom

+2

@Absolom : 기술적으로 스레드 풀 작업 스케줄러에서 실행 중입니다. 이상한 행동은 스레드 풀 작업 스케줄러가 스레드가 해당 컨텍스트의 일부임을 결정하기 때문입니다. –

+0

설명해 주셔서 고맙습니다.하지만 제 예제에서 "After Method1"이 스레드 풀 작업 스케줄러에 의해 예약되고 실제로 같은 스레드가 아닌 스레드 풀에서 실행되는 이유를 설명 할 수 있습니까? 비동기와 작업 모두에서 왜 같은 동작을하지 않습니까? – Absolom