Der Hauptpunkt ist, dass Sie die asynchronen Operationen haben möchten, auf die Sie warten müssen, damit sie nicht auf dem UI-Thread passieren. Die Lösung von Yuri macht das, aber Sie können auch Ihre asynchronen Operationen ausführen und dann, wenn Sie Aktualisierungen an der Benutzeroberfläche vornehmen müssen, müssen Sie diese nur auf dem UI-Thread ausführen, um zu verhindern, dass die Benutzeroberfläche gesperrt wird.
Das eigentliche Problem kommt davon, wie Ihre Threads arbeiten. Wenn Sie diese Echtzeit sehen möchten, öffnen Sie das Threads-Debug-Pad in Xamarin Stud und beobachten Sie die Threads, während Sie den Code durchgehen.
Lassen Sie uns Ihren Code als Beispiel:
private void Button_Clicked(object sender, EventArgs e)
{
var btn = (Button)sender;
btn.Text = "Wait";
...
Als wir die "Button_Clicked" Event-Handler geben, sind wir nun auf dem UI-Thread. Woher wissen wir? weil der Benutzer auf den Button geklickt hat und wir hier sind. Alles wurde im Hauptthread der Benutzeroberfläche ausgeführt. Was auch immer wir als nächstes in unserem Code tun, wird weiterhin auf diesem Thread laufen, wenn das Betriebssystem nicht bestimmt, dass es die Threads aus irgendeinem Grund verwalten muss (Leistung, so funktioniert das OS usw.).
Wenn Ihr Code eine asynchrone Aufgabe ausführt, wie das Senden eines Webanforderungsaufrufs, um Daten aus einer REST-API abzurufen, müssen Sie sich bewusst sein, auf welchem Thread Sie sich befinden. Wir können nicht garantieren, dass unser Webanforderungsaufruf auf dem UI-Thread oder einem Thread ohne manuelle Bearbeitung ausgeführt wird. Das ist der Vorteil unserer fortschrittlichen Betriebssysteme, die für uns die Mehrkern-Multi-Thread-Bearbeitung übernehmen.
Aus diesem Grund möchten wir sicherstellen, dass alle Aktualisierungen der Benutzeroberfläche auf dem UI-Thread geschehen. Die richtige Lösung für Ihren Code würde unten sein:
private async void Btn1_Clicked(object sender, EventArgs e)
{
var btn = (Button)sender;
btn.Text = "Wait";
...some code...maybe async or not (take out async above if not)
Device.BeginInvokeOnMainThread(() =>
{
btn.Text = "Do Something";
});
}
Dies funktioniert für uns, weil wir Xamarin.Forms sagen, dass Befehl auf dem Haupt-Thread ausgeführt werden. Xamarin.Forms macht den Haupt-UI-Thread auf diese Weise verfügbar. Eine andere Möglichkeit wäre, den Kontext unseres UI-Threads zu nehmen und zwischenzuspeichern, um ihn bei Aktualisierungen zu verwenden. Dies wird normalerweise in Xamarin.Android- und Xamarin.iOS-Anwendungen ausgeführt.
Der eigentliche Weg, all dies zu tun, ist durch Datenbindungen. Xamarin.Forms wurde mit der Absicht erstellt, mit einem Model-View-ViewModel (MVVM) -Muster verwendet zu werden. Xamarin.Forms Bindings behandelt alle Kontextwechsel für Sie, wenn Sie OnPropertyChanged
aufrufen. Auf diese Weise können Sie einfach die Eigenschaft in Ihrem ViewModel aktualisieren, die an den Text Ihrer Schaltflächen gebunden ist.
Ich hoffe, dies hilft ein besseres Verständnis von dem, was auf der Thread-Ebene passiert!
Disclosure: Ich arbeite für Xamarin/Microsoft
Der UI-Thread, indem Sie Ihre Codeausführung blockiert wird. Sie müssen den Button-Text in einem separaten Thread ändern –
Vielen Dank für die Info Sandeep! –