2012-12-05 12 views
14

Mögliche Duplizieren:
How to call an async method from a getter or setter?Verwendung erwarten innerhalb Eigenschaften in C#

ich eine Immobilie zu implementieren bin versucht, die die Sqlite warten im Inneren verwenden werden:

public int ID { 
     get 
     { 
      if (_id != null) 
      { 
       return _id; 
      } 
      if (string.IsNullOrEmpty(ImageName)) 
      { 
       return -1; 
      } 
      var query = CurrentConnection.Table<Image>().Where(i => i.ImageName == ImageName); 
      var result = await query.ToListAsync(); 
      ...other code 

Da jedoch eine Eigenschaft nicht auf "Warten" eingestellt ist (das hat versucht, funktioniert nicht), kann ich nicht erwarten in einer Eigenschaft verwenden.

Gibt es einen Weg, um dies zu umgehen neben einer Methode anstelle einer Eigenschaft?

+1

Verwenden Sie einfach die synchrone Version. –

+3

Sie haben einen Rekursion Bug. sollte sein 'if (_id! = null) return _id; 'nicht' ID' –

+5

Ich würde erwarten, dass die Eigenschaften klein und schnell sind. Alles was mit Warten zu tun hat, sollte in einer Methode gehen, wenn du mich fragst. Nur sagen ... –

Antwort

10

Nein - Async-Eigenschaften gibt es nicht. Selbst wenn Sie könnten eine asynchrone Eigenschaft deklarieren, müsste es mit einem Rückgabewert von Task<int> anstelle von int deklariert werden ... sonst was möchten Sie zurückgeben, wenn Sie einen Ausdruck await treffen?

Ich würde stark schlagen Sie eine GetIdAsync Methode hier, vorausgesetzt, Sie wollen auf jeden Fall Async-Verhalten.

+2

Beachten Sie auch, dass, wenn es eine Eigenschaft des Typs "Task " ist, es Setter * wirklich * seltsam machen würde. – Servy

+1

@Servy: Sehr wahr :) –

+1

Da async/await nicht in Verbindung mit Ertragsrückgabeblöcken verwendet werden kann, wäre ein sinnvoller Kompromiss die manuelle Implementierung von IEnumerator >, wobei die Eigenschaft Current async ist. Diese Regel, dass Async nicht für Eigenschaften verwendet werden kann, ist eine stilistische Einschränkung, die dieses nützliche Muster ausschließt. Die einzige Lösung besteht nun darin, * internen * Iterationsdetails den Clients zur Verfügung zu stellen, damit sie die Iteration manuell durchführen können. Schrecklich. – naasking

0

Wenn Sie warten verwenden, verwandeln Sie den Rest der Methode in einen Rückruf, was bedeutet, dass Sie kein int zurückgeben können. Sie müssten eine Task < int> zurückgeben. Derzeit gibt es auch keine Unterstützung für die Verwendung von "erwarten" in einer Eigenschaft. Sie müssten die Eigenschaft in eine "get" -Methode konvertieren, die den Task < int> zurückgibt.

Wenn Sie die int direkt zurückkehren möchten, statt awaitable, awaitable .RESULT verwenden warten zu tun. Dies führt dazu, dass die asynchrone Aktion synchron aufgelöst wird, sodass Sie das konkrete Ergebnis direkt zurückgeben können.

+3

Das Ausführen einer Datenbankabfrage innerhalb eines Eigenschaftengetters wird jedoch allgemein als eine schlechte Idee angesehen. Property Getter sollten schnell und einfach sein. – Servy

+0

Es hängt davon ab, was der Hauptzweck der Immobilie ist. Wenn das Objekt ein DbLoggedInUser-Objekt ist und die Eigenschaft FirstName ist, erscheint es sinnvoll, dass die Eigenschaft im Hintergrund eine Datenbankabfrage durchführt. Sie haben jedoch recht, dass Eigenschaften generell einfach sein sollten und nicht ausfallen können. – SecurityMatt

+0

Es wäre niemals vernünftig, eine Datenbankabfrage im Hintergrund des Getters einer Eigenschaft durchzuführen. -- Das ist einfach falsch. - Das * muss * ein Methodenaufruf sein. – BrainSlugs83

4

Sie sollten eine Eigenschaft Getter nicht für irgendetwas außer der Rückgabe eines Variablenwerts verwenden.

Durch den Aufruf von Code werden häufig leistungsbezogene Annahmen getroffen, was beim Anrufen Ihrer Kurse zu erwarten ist.

Daumenregel:

  • Eigenschaften implizieren eine sehr schnell Rückgabe eines Wertes
  • Methoden bedeuten mehr oder weniger langwierige Operationen

Deshalb Es ist stark empfohlen, keine langwierige Logik in einen Getter zu stecken. Verwenden Sie stattdessen Methoden.

Microsofts Ricos Mariany gibt einen sehr ausführlichen Artikel darüber hier: Performance Guidelines for Properties

+0

Service-Fabric verfügt über asynchrone Wörterbücher, um Statusobjekte zu erhalten - es ist sehr schnell und sie machen es überall in Codebeispielen. - Es scheint in 90% der Fälle sehr billig zu sein. - Aber es ist so viel mehr Code zu schreiben, als nur eine Immobilie zu ergattern. - Dafür muss es eine Lösung geben. :( – BrainSlugs83

+0

@ BrainSlugs83: Verstehe ich richtig, dass Sie mich abmelden, weil Sie die Implementierung von zuverlässiger Sammlung von Microsoft nicht mögen ...? –

9

Es gibt keinen technischen Grund, dass async Eigenschaften nicht in C# erlaubt.Es war eine gezielte Designentscheidung, denn "asynchrone Eigenschaften" sind ein Oxymoron.

Eigenschaften sollten aktuelle Werte zurückgeben; Sie sollten keine Hintergrundoperationen starten. Normalerweise

, wenn jemand eine „asynchrone Eigenschaft“ will, was sie wirklich wollen, ist eine davon:

  1. Eine asynchrone Methode, die einen Wert zurückgibt. Ändern Sie in diesem Fall die Eigenschaft in eine async Methode.
  2. Ein Wert, der bei der Datenbindung verwendet werden kann, aber asynchron berechnet/abgerufen werden muss. Verwenden Sie in diesem Fall entweder eine async Factory-Methode für das enthaltene Objekt oder verwenden Sie eine async InitAsync()-Methode. Der datengebundene Wert wird default(T) sein, bis der Wert berechnet/abgerufen wird.
  3. Ein Wert, der teuer zu erstellen ist, aber für zukünftige Verwendung zwischengespeichert werden sollte. Verwenden Sie in diesem Fall AsyncLazyfrom my blog oder AsyncEx library. Dies wird Ihnen eine await fähige Eigenschaft geben.
Verwandte Themen