次のコードの動作について理解していないことがいくつかありますが(主なものは1つあります)await/async同期のコンテキスト切り替え動作の説明方法
誰かがこれを説明できますか?
実際には非常に単純なコードです。非同期メソッドを呼び出す1つの通常のメソッドです。また、非同期メソッドでは、usingブロックを使用してSynchronizationContextを一時的に変更しようとします。
コード内の異なる点で、私は現在のSynchronizationContextを調べます。ここで
は私の質問です: 実行は、 "2.1" は、文脈が コンテキスト#2に変更された位置に到達した- 。はい。次に、 `await`をヒットしたので、Taskは に戻り、実行は1.2の位置にジャンプします。なぜ、 の位置1.2では、コンテキストはコンテキスト2で「スティック」ではないのですか?
ここでは、usingステートメントと非同期メソッドでいくつかの魔法が行われていますか?
- 位置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