मैं पहली बार कोड डाल चाहते हैं और उसके बाद स्थिति स्पष्ट और मेरे सवाल पर आधारित है कि पूछने के साथ इंतजार है:async/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
विधि false
पर पैरामीटर सेट किया है। तो, यह इंगित करता है कि मैं SynchronizationContext.Current
के अंदर निष्पादित होने की मेरी निरंतरता नहीं चाहता हूं। अब तक सब ठीक है।
दूसरे await
उपयोग पर (GetStringAsync
विधि के साथ), मैंने ConfigureAwait
विधि को कॉल नहीं किया था। इसलिए, मैंने मूल रूप से संकेत दिया कि GetStringAsync
विधि की निरंतरता के लिए वर्तमान सिंक्रनाइज़ेशन संदर्भ पर वापस आने के लिए चाहते हैं। इसलिए, जैसा कि आप देख सकते हैं, मैं निरंतरता के अंदर TextBlock.Text
(जो यूआई थ्रेड से संबंधित) संपत्ति सेट करने का प्रयास करता हूं।
जब मैं आवेदन चलाने के लिए और बटन क्लिक करें, मैं एक अपवाद मुझे निम्न संदेश दे रही है मिलती है: क्योंकि एक अलग धागा यह मालिक
बुला धागा इस वस्तु का उपयोग नहीं कर सकते हैं।
सबसे पहले, यह मेरे लिए कोई मतलब नहीं बनाया है और मैंने सोचा था कि मैं एक बग की खोज की है, लेकिन फिर, मैंने महसूस किया कि GetStringAsync
एक और धागा (अत्यधिक संभावना) जो यूआई धागा तुलना में अलग है और कोई है में निष्पादित किया जा सकता सिंक संदर्भ के लिए ज्ञान क्योंकि continueOnCapturedContext
false
पर Task
के लिए सेट किया गया है जो httpClient.GetAsync
विधि से वापस लौटाया गया है।
क्या यह मामला यहां है? इसके अलावा, इस मामले में, GetStringAsync
विधि को यूआई थ्रेड पर वापस पोस्ट करने का मौका है httpClient.GetAsync विधि निरंतरता UI थ्रेड के अंदर निष्पादित की जा सकती है?
मेरे पास कोड के अंदर कुछ टिप्पणियां भी हैं। कोड के अंदर मेरे प्रश्नों और टिप्पणियों को ध्यान में रखते हुए, क्या मुझे यहां कुछ याद आ रही है?
क्या यह उत्तर मदद करता है? http://stackoverflow.com/a/12357113/171121 –