ich zum ersten Mal den Code setzen möchte und dann die Situation erklären und meine Frage basiert darauf, dass:async/warten mit ConfigureAwait des continueOnCapturedContext Parameter und SynchronizationContext für asynchrone Fortsetzungen
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...";
}
}
Dies ist eine ziemlich einfache WPF Probe, die läuft auf .NET 4.5 und macht wahrscheinlich keinen großen Sinn, aber das sollte mir helfen, meine Situation zu erklären.
Ich habe eine Schaltfläche auf dem Bildschirm, die ein asynchrones Klickereignis hat. Wenn Sie sich den Code GetValuesAsync
ansehen, sehen Sie zweimal die Verwendung des Schlüsselwortes await
. Bei der ersten Verwendung habe ich den continueOnCapturedContext
Parameter der Task.ConfigureAwait
Methode auf false
gesetzt. Also, dies zeigt an, dass ich nicht unbedingt meine Fortsetzung innerhalb der SynchronizationContext.Current
ausgeführt werden soll. So weit, ist es gut.
Bei der zweiten await
Nutzung (mit der GetStringAsync
Methode), habe ich nicht die ConfigureAwait
Methode aufgerufen. Also, ich habe im Grunde angegeben, dass ich möchte, um zurück zum aktuellen Synchronisationskontext für die Fortsetzung der GetStringAsync
Methode zu bekommen. Wie Sie sehen können, versuche ich die Eigenschaft TextBlock.Text
(die zum UI-Thread gehört) innerhalb der Fortsetzung zu setzen.
Wenn ich die Anwendung ausführen und auf die Schaltfläche klicken, erhalte ich eine Ausnahme mir die folgende Meldung geben:
Der aufrufende Thread kann nicht auf dieses Objekt, weil ein anderer Thread es besitzt.
Zuerst machte dies keinen Sinn für mich, und ich dachte, dass ich einen Fehler entdeckt, aber dann merkte ich, dass GetStringAsync
kann (sehr wahrscheinlich) in einem anderen Thread ausgeführt werden, die als der UI-Thread unterschiedlich ist und haben keine Wissen für den Sync-Kontext, weil continueOnCapturedContext
auf false
für die Task
gesetzt ist, die von httpClient.GetAsync
Methode zurückgegeben wird.
Ist dies der Fall hier? Gibt es in diesem Fall auch eine Möglichkeit, dass die Methode GetStringAsync
zurück an den UI-Thread gesendet wird, da die httpClient.GetAsync-Methodenfortsetzung im UI-Thread ausgeführt werden kann?
Ich habe auch ein paar Kommentare in den Code. In Anbetracht meiner Fragen und der Kommentare innerhalb des Codes, vermisse ich hier etwas?
Hilft diese Antwort? http://stackoverflow.com/a/12357113/171121 –