我想首先把代碼,然後說明情況,並要求根據我的問題:異步/等待與ConfigureAwait的continueOnCapturedContext參數的SynchronizationContext用於異步連續
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private async void Button_Click_2(object sender, RoutedEventArgs e) {
var result = await GetValuesAsync();
Foo.Text += result;
}
public async Task<string> GetValuesAsync() {
using (var httpClient = new HttpClient()) {
var response = await httpClient
.GetAsync("http://www.google.com")
.ConfigureAwait(continueOnCapturedContext: false);
// This is the continuation for the httpClient.GetAsync method.
// We shouldn't get back to sync context here
// Cuz the continueOnCapturedContext is set to *false*
// for the Task which is returned from httpClient.GetAsync method
var html = await GetStringAsync();
// This is the continuation for the GetStringAsync method.
// Should I get back to sync context here?
// Cuz the continueOnCapturedContext is set to *true*
// for the Task which is returned from GetStringAsync
// However, GetStringAsync may be executed in another thread
// which has no knowledge for the sync context
// because the continueOnCapturedContext is set to *false*
// for the Task which is returned from httpClient.GetAsync method.
// But, on the other hand, GetStringAsync method also has a
// chance to be executed in the UI thread but we shouldn't be
// relying on that.
html += "Hey...";
Foo.Text = html;
return html;
}
}
public async Task<string> GetStringAsync() {
await Task.Delay(1000);
return "Done...";
}
}
這是一個相當簡單的WPF樣品,其運行在.NET 4.5上,可能沒有多大意義,但這應該有助於我解釋我的情況。
我有一個按鈕,在屏幕上有一個異步點擊事件。當您查看GetValuesAsync
代碼時,您會看到await
關鍵字的兩次使用情況。隨着第一次使用,我將Task.ConfigureAwait
方法的continueOnCapturedContext
參數設置爲false
。所以,這表明我不需要我的繼續在SynchronizationContext.Current
內執行。到現在爲止還挺好。
在第二個await
的用法(與GetStringAsync
方法),我沒有撥打ConfigureAwait
方法。所以,我基本上表明,我想想要回到當前的同步上下文爲繼續GetStringAsync
方法。所以,正如你所看到的,我嘗試在延續中設置TextBlock.Text
(屬於UI線程)屬性。
當我運行應用程序,並單擊按鈕,我得到一個異常給我下面的消息:因爲不同的 線程擁有它
調用線程不能訪問該對象。
起初,這沒有任何意義,我和我想我發現了一個錯誤,但那時,我意識到GetStringAsync
可能在另一個線程(很有可能),這是比UI線程不同,並沒有被執行因爲對於從httpClient.GetAsync
方法返回的Task
,continueOnCapturedContext
設置爲false
。
這是這裏的情況嗎?此外,在這種情況下,是否有機會將GetStringAsync
方法回發給UI線程bacuse httpClient.GetAsync方法的延續可能會在UI線程內執行?
我在代碼裏面也有一些註釋。鑑於我的問題和代碼中的評論,我在這裏錯過了什麼?
此答案有幫助嗎? http://stackoverflow.com/a/12357113/171121 –