다음 코드의 동작에 대해 이해할 수없는 몇 가지 사항 (그러나 1 가지 주요 사항)이 있습니다.await/async 동기화 컨텍스트 전환 동작을 설명하는 방법
누군가 설명해 드릴 수 있습니까?
사실 아주 간단한 코드입니다. 비동기 메서드를 호출하는 하나의 일반 메서드입니다. 비동기 메서드에서는 using 블록을 사용하여 SynchronizationContext를 일시적으로 변경하려고합니다.
코드의 다른 지점에서 현재 SynchronizationContext를 조사합니다. 여기
내 질문은 다음과 같습니다 실행이 "2.1"문맥 상황 # 2로 변경 한 위치에 도달- . 괜찮아. 그러면 우리는`await`을 만나기 때문에 Task는 이 리턴되고 실행은 1.2로 되돌아갑니다. 그렇다면 위치 1.2에서 컨텍스트가 컨텍스트 # 2에서 "고정"되지 않는 이유는 무엇입니까?
아마도 여기에 using 문과 async 메서드가있는 마법이 있습니까?
- 위치 2.2에서 컨텍스트가 컨텍스트 # 2가 아닌 이유는 무엇입니까? 컨텍스트가 "연속"('await'이후의 명령문)으로 이어지지 않아야합니까?
코드 :
public class Test
{
public void StartHere()
{
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
this.logCurrentSyncContext("1.1"); // Context #1
Task t = f();
this.logCurrentSyncContext("1.2"); // Context #1, why not Context #2?
t.Wait();
this.logCurrentSyncContext("1.3"); // Context #1
}
private async Task f()
{
using (new ThreadPoolSynchronizationContextBlock())
{
this.logCurrentSyncContext("2.1"); // Context #2
await Task.Delay(7000);
this.logCurrentSyncContext("2.2"); // Context is NULL, why not Context #2?
}
this.logCurrentSyncContext("2.3"); // Context #1
}
// Just show the current Sync Context. Pass in some kind of marker so we know where, in the code, the logging is happening
private void logCurrentSyncContext(object marker)
{
var sc = System.Threading.SynchronizationContext.Current;
System.Diagnostics.Debug.WriteLine(marker + " Thread: " + Thread.CurrentThread.ManagedThreadId + " SyncContext: " + (sc == null? "null" : sc.GetHashCode().ToString()));
}
public class ThreadPoolSynchronizationContextBlock : IDisposable
{
private static readonly SynchronizationContext threadpoolSC = new SynchronizationContext();
private readonly SynchronizationContext original;
public ThreadPoolSynchronizationContextBlock()
{
this.original = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(threadpoolSC);
}
public void Dispose()
{
SynchronizationContext.SetSynchronizationContext(this.original);
}
}
}
결과 :
1.1 Thread: 9 SyncContext: 37121646 // I call this "Context #1"
2.1 Thread: 9 SyncContext: 2637164 // I call this "Context #2"
1.2 Thread: 9 SyncContext: 37121646
2.2 Thread: 11 SyncContext: null
2.3 Thread: 11 SyncContext: 37121646
1.3 Thread: 9 SyncContext: 37121646
2.2 : https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Task.cs,2976 – PetSerAl
1.2 : http://referencesource.microsoft.com/#mscorlib/system/runtime/compilerservices /AsyncMethodBuilder.cs,320 – PetSerAl
컨텍스트 블록이 GC 아래에있는 것 같습니다. 'Dispose' 통화 시간을 확인 했습니까? – VMAtm