Wie zu verwenden Sie erwarten in Xamarin Android-Aktivität Rückrufe
Der Titel mag ein wenig irreführend, meine Frage ist mehr warum es funktioniert auf diese komische Art und Weise.
So, ich habe eine Aktivität mit einem layout, das eine TextView und eine ListView. Ich habe eine lang laufende asynchrone Methode, bereitet die Daten werden in der Liste angezeigt. Also der erste code ist wie folgt:
protected async override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.MyView);
await SetupData();
}
private async Task SetupData(){
Task.Run(async () => {
var data = await new SlowDataLoader().LoadDataAsync();
//For simplicity setting data on the adapter is omitted here
});
}
Es funktioniert, in dem Sinne, dass es ausgeführt, ohne Fehler. Allerdings ist die Tätigkeit erscheint wie ein leerer Bildschirm, und sogar die text-Ansicht rendert nur nach einer bestimmten Verzögerung. So scheint es, dass die Aufgabe tatsächlich nicht asynchron ausgeführt wird. Einstellung ConfigureAwait(false) auf "warten" fordert, hat nicht geholfen. Verschieben der SetupData () - Aufruf in OnPostCreate, OnResume und OnPostResume hat keine Wirkung. Die einzige Sache, die die TextView erscheinen sofort und Rendern Sie die Liste später, wenn Daten angekommen ist:
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.MyView);
new Handler().PostDelayed(async ()=>{
await SetupData();
}, 100);
}
Die Frage ist also, warum nicht
await SetupData().ConfigureAwait(false);
Blockierung der Strömung? Warum tun wir uns dazu zwingen müssen, verzögern den start der asynchronen operation zu lassen, UI fertig stellen, Rendern, obwohl (nach dieser http://www.wintellect.com/devcenter/paulballard/tasks-are-still-not-threads-and-async-is-not-parallel) SetupData soll in der Lage sein zu laufen als separater thread hier ?
p.s. entfernen Sie den code, setzt Daten auf dem adapter hat keinen Einfluss auf dieses Verhalten - es gibt immer noch eine Verzögerung, bevor der Bildschirm gerendert wird. Also ich bin mir nicht angezeigt, dass der code hier.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Durch warten auf innerhalb des UI-Looper, Sie blockiert die weitere Ausführung von code auf den thread, während Ihr
SetupData
Methode ausgeführt wird.Non-blocking Beispiel:
Ausgabe:
Task.Run
, aber die Methode und damit den thread, dass ist erwartening ist suspendiert worden, bis das warten aufed - Betrieb zurück.Zur Ergänzung der Antwort von @SushiHangover, ich bin das hinzufügen meiner eigenen Antwort auf die tatsächlichen Fehler und die Liste möglicher Lösungen, zusätzlich zu dem Vorschlag von @SushiHangover.
Betrachten Sie das Beispiel ganz unten auf dieser Seite https://msdn.microsoft.com/en-us/library/hh156528.aspx
Das eigentliche problem in der original code (und alle anderen Varianten, die ich ausprobiert habe) war, dass, obwohl SetupData wurde erklärt wie async-Methode war es eigentlich laufen synchron. Also, wenn OnCreate wurde warten auf eine synchrone Methode, es blockiert wurde (genau das, was Sie demo im Beispiel oben). Dieses Problem kann behoben werden, über mehrere Wege. Zunächst wird, wie SushiHangover vorgeschlagen, nicht erwarten, auf diese Methode, und da ist es sync, rufen Sie es als solche (und möglicherweise auch entfernen async-Schlüsselwort und "void" zurückgeben von ihm).
Anderen Ansatz, die möglicherweise besser geeignet, in bestimmten Situationen zu erwarten, die auf die Aufgabe, die innerhalb dieser Methode:
Oder ändern Sie diese Methode, um die Einhaltung async-Methode Anforderungen durch Rücksendung der Aufgabe:
Diese beiden Veränderungen erlauben, den erwarten in der OnCreate-wie erwartet - OnCreate-Methode beendet wird, während die Daten noch geladen werden.
CalledFromWrongThreadException
, da Sie ändernView
s von einem worker-thread.Weil es nicht läuft auf dem UI-Thread dies kann Ihnen helfen, eine klarere Sicht Was ist die Android-UiThread (UI-thread)