Asynchrone Implementierung von IValueConverter
Wenn eine asynchrone Methode, die ich verwenden möchte, um Auslöser in einem IValueConverter.
Gibt es eine bessere Warten Sie dann zwingen, es zu werden synchron durch Aufruf der result-Eigenschaft?
public async Task<object> Convert(object value, Type targetType, object parameter, string language)
{
StorageFile file = value as StorageFile;
if (file != null)
{
var image = ImageEx.ImageFromFile(file).Result;
return image;
}
else
{
throw new InvalidOperationException("invalid parameter");
}
}
InformationsquelleAutor der Frage Boas Enkler | 2013-02-21
Du musst angemeldet sein, um einen Kommentar abzugeben.
Werden Sie wahrscheinlich nicht wollen, zu nennen
Task.Result
, für ein paar Gründe.Erstens, wie ich im detail erklären, auf meinem blog, Sie können deadlock es sei denn, Ihr
async
code ist geschrieben worden überConfigureAwait
überall. Zweitens, werden Sie wahrscheinlich nicht wollen, (synchron -) block UI; besser wäre es, vorübergehend einblenden "wird geladen..." oder leere Bild beim Lesen von der Festplatte, und update, wenn das Lesen abgeschlossen ist.So, ich persönlich würde das Teil in meinem ViewModel, nicht ein Wert-Konverter. Ich habe einen blog-Beitrag beschreibt einige databinding-freundlichen Möglichkeiten, um die asynchrone Initialisierung. Das wäre meine erste Wahl. Es fühlt sich einfach nicht richtig an eine Wert Konverter Auftakt asynchrone hintergrund-Operationen.
Jedoch, wenn Sie als habe Sie Ihr design und denke wirklich, dass eine asynchrone Wert Konverter, was Sie brauchen, dann muss man ein bisschen erfinderisch. Das problem mit Wert-Wandlern ist, dass Sie haben synchron sein: die Datenbindung beginnt bei den Daten-Kontext, wertet Sie den Pfad, und dann startet eine Konvertierung. Nur die Daten, die Kontext-und Pfad-support-Benachrichtigungen ändern.
Also, Sie haben, um einen (synchronen) Wert-Konverter in Ihrem datenkontext, um wandeln Sie Ihre original-Wert in einem databinding-freundliche
Task
-wie-Objekt und dann Ihr Eigentum-Bindung nur eine der Eigenschaften auf dieTask
-wie Objekt, um das Ergebnis zu erhalten.Hier ist ein Beispiel was ich meine:
Den
TextBox
ist nur ein Eingabe-Feld. DieTextBlock
setzt zuerst seine eigenenDataContext
zu denTextBox
's input text läuft über eine "asynchrone" - Konverter.TextBlock.Text
eingestellt ist, um dieResult
von diesem Konverter.Der Konverter ist Recht einfach:
Den Konverter zum ersten mal startet eine asynchrone operation warten Sie 5 Sekunden und fügen Sie dann " fertig!" an das Ende des input-string. Das Ergebnis der Konverter kann nicht nur eine schlichte
Task
weilTask
nicht umsetzenIPropertyNotifyChanged
, also ich bin mit einem Typ, der sein wird in der nächsten Version von meinem AsyncEx Bibliothek. Es sieht wie folgt aus (vereinfacht für dieses Beispiel; volle Quelle ist erhältlich):Indem Sie diese Stücke zusammen, die wir erstellt haben, eine asynchrone Daten-Kontext, ist das Ergebnis ein Wert Konverter. Die databinding-freundliche
Task
- wrapper verwenden Sie einfach die Standardeinstellung Ergebnis (in der Regelnull
oder0
), bis dieTask
abgeschlossen. Also der wrapper istResult
ist ganz anders alsTask.Result
: es wird nicht synchron block und es besteht keine Gefahr von Deadlocks.Aber noch einmal betonen: ich würde entscheiden, asynchrone Logik in die ViewModel-eher als eine Wert-Konverter.
InformationsquelleAutor der Antwort Stephen Cleary