Sau khi đọc Stephen Toub's article on SynchronizationContext tôi là trái với một câu hỏi về đầu ra của mảnh này của .NET 4.5 mã:SynchronizationContext chảy trên Task.Run nhưng không phải trên chờ đợi
private void btnDoSomething_Click()
{
LogSyncContext("btnDoSomething_Click");
DoItAsync().Wait();
}
private async Task DoItAsync()
{
LogSyncContext("DoItAsync");
await PerformServiceCall().ConfigureAwait(false); //to avoid deadlocking
}
private async Task PerformServiceCall()
{
LogSyncContext("PerformServiceCall 1");
HttpResponseMessage message = await new HttpClient
{
BaseAddress = new Uri("http://my-service")
}
.GetAsync("/").ConfigureAwait(false); //to avoid deadlocking
LogSyncContext("PerformServiceCall 2");
await ProcessMessage(message);
LogSyncContext("PerformServiceCall 3");
}
private async Task ProcessMessage(HttpResponseMessage message)
{
LogSyncContext("ProcessMessage");
string data = await message.Content.ReadAsStringAsync();
//do something with data
}
private static void LogSyncContext(string statementId)
{
Trace.WriteLine(String.Format("{0} {1}", statementId, SynchronizationContext.Current != null ? SynchronizationContext.Current.GetType().Name : TaskScheduler.Current.GetType().Name));
}
Đầu ra là:
btnDoSomething_Click WindowsFormsSynchronizationContext
DoItAsync WindowsFormsSynchronizationContext
PerformServiceCall 1 WindowsFormsSynchronizationContext
PerformServiceCall 2 ThreadPoolTaskScheduler
ProcessMessage ThreadPoolTaskScheduler
PerformServiceCall 3 ThreadPoolTaskScheduler
Nhưng tôi mong chờ PerformServiceCall 1 tới không được vào WindowsFormsSynchronizationContext kể từ khi bài báo nói rằng "SynchronizationContext. Hiện tại không "chảy" qua các điểm chờ "...
Bối cảnh không có được thông qua khi gọi PerformServiceCall với Task.Run và một lambda async, như thế này:
await Task.Run(async() =>
{
await PerformServiceCall();
}).ConfigureAwait(false);
bất cứ ai có thể làm rõ hoặc chỉ vào một số tài liệu về vấn đề này?
Cuộc gọi ConfigureAwait() sẽ không có bất kỳ ảnh hưởng nào cho đến khi Tác vụ thực sự bắt đầu chờ. Điều đó đã không xảy ra, cuộc gọi LogSyncContext() của bạn đã đến sớm. Di chuyển nó sau khi chờ đợi. –
Đó không phải là bế tắc trên 'DoItAsync(). Đợi();'? –
Không, nó không phải là bế tắc nhờ vào cuộc gọi ConfigureAwait – Stif