Dangling erwartet und mögliche Speicherlecks in der asynchronen Programmierung

8

Der Fluss, der erwartet in .NET 4.5 und Async CTP 4.0 enthält, kann aus verschiedenen Gründen stecken, z. da der Remote-Client nicht geantwortet hat. Natürlich ist WaitForAny, wenn wir auch auf eine Timeout-Aufgabe warten, eine offensichtliche Lösung für die Wiederherstellung des High-Level-Flusses. Dies löst jedoch nicht alle möglichen Probleme.

Ich habe folgende Fragen:

  1. Was passiert mit dem Kontext von await , das niemals zurückgegeben wird? Ich verstehe, dass dies zu Speicherverlust führen wird. Habe ich recht?

  2. Wie kann ich entweder im Debugger oder über die entsprechende API prüfen, wie viele " aware" "" "in der Anwendung vorhanden sind?

  3. Ist es möglich, sie global aufzuzählen?

  4. Wenn 3. korrekt ist, ist es möglich, die Aufgaben für diese * abzuwarten * s (d. h. aufzuräumen) zu stornieren?

Hinweis: In Frage 4 werde ich nicht nach Abbruchelementen gefragt, die bei der expliziten Aufgabenerstellung verwendet werden sollen. Ich meine den Fall, als die Aufgabe indirekt erstellt wurde:

%Vor%

Motivation für diese Frage:

  1. Der Versuch, Speicherlecks zu vermeiden
  2. Versuche, den Code mit zu vielen Fällen, in denen Stornierungs-Token enthalten sind, zu komplizieren
  3. In vielen Situationen ist das Zeitlimit nicht im Voraus für jeden Low-Level-Task bekannt, aber der High-Level-Flow kann nur den Recovery-Ansatz verwenden: "Wir stecken fest? Macht nichts, reinige nur und lass uns von vorne anfangen" / li>
Yuri S. 18.10.2012, 11:17
quelle

2 Antworten

6
  

1 Was passiert mit dem Kontext von "Warten", der niemals wiederkehrt?

Ich glaube, das führt zu einem Speicherverlust (wenn Sie eine E / A-Operation ausführen). Am besten vervollständigen Sie immer Ihre await s (und das bedeutet Immer haben Ihre Task Methoden früher oder später zurückzukehren.)

Aktualisierung von svicks Kommentar: Es gibt Situationen , wo dies nicht einen Speicherverlust verursachen würde.

  

2 Wie kann ich entweder im Debugger oder über die entsprechende API prüfen, wie viele hängende "Avatare" in der Anwendung existieren?

Ich bin mir nicht sicher, ob es einen einfachen Weg dafür gibt. Ich glaube, es sollte möglich sein, ein Debugger-Plugin zu schreiben, das SoS verwendet, um existierende Heap-Objekte zu finden, die mit dem Muster der vom Compiler generierten asynchronen Zustandsautomaten übereinstimmen.

Aber das ist eine Menge Arbeit für wenig Nutzen.

  

3 Ist es möglich, sie global aufzuzählen?

Nicht mit den normalen APIs.

  

Wenn 3 korrekt ist, ist es möglich, die Löschung der Aufgaben für diese zu erzwingen (d. h. aufzuräumen)?

Selbst wenn Sie sie zur Laufzeit aufzählen könnten (z. B. über die Profiling-API), können Sie die Löschung für eine Aufgabe nicht erzwingen. Stornierung ist kooperativ.

Der richtige Weg, um damit fertig zu werden, ist die Standardunterdrückung. Das Dokument Aufgabebasiertes asynchrones Muster gibt Richtlinien für abbrechbare Methoden async vor.

Auf der niedrigsten Ebene: Viele async APIs in der BCL nehmen ein optionales async .

Auf einer mittleren Ebene: Es ist üblich, dass eine CancellationToken -Methode eine optionale async verwendet und sie einfach an andere CancellationToken -Methoden weiterleitet.

Auf der höchsten Ebene: Es ist einfach zu erstellen ein async , das danach ausgelöst wird eine bestimmte Zeit.

    
Stephen Cleary 18.10.2012 13:55
quelle
0

Über die Fragen 2 und 3 habe ich keine wirkliche Antwort.

  1. Ich bezweifle es, solange die in der Aufgabe verwendeten Ressourcen ordnungsgemäß entsorgt werden, wenn die CLR die Aufgabe beim Beenden der Anwendung abstellt.

Aufgaben, die nie wiederkehren, sind selten eine gute Sache. Um dies zu vermeiden und Punkt 4 zu beantworten, können Aufgaben abgebrochen werden.

Sie müssen ein Cancellingtoken erstellen, das Sie an die Aufgabe übergeben. Die Aufgabe ist selbst dafür verantwortlich, nach dem Status des Abbruch-Tokens Ausschau zu halten und eine Ausnahme auszulösen, wenn sie abgebrochen wird. (Mehrere Aufgaben können gleichzeitig mit demselben Token abgebrochen werden.)

Dieser Artikel in MSDN zeigt Ihnen dies.

    
lboshuizen 18.10.2012 12:07
quelle