Frage

Ich bin im Allgemeinen vorsichtig Schnittstellen teilweise umzusetzen. Allerdings IAsyncResult ist ein bisschen ein Sonderfall, da es mehrere ganz unterschiedliche Nutzungsmuster unterstützt. Wie oft haben Sie / siehe AsyncState / AsyncCallback Muster verwendet wird, im Gegensatz zu nur EndInvoke Aufruf, mit AsyncWaitHandle oder Polling IsCompleted (igitt)?

Verwandte Frage: Erkennen, dass ein Threadpool WorkItem hat abgeschlossen / warten auf Abschluss .

Betrachten Sie diese Klasse (sehr ungefähre, benötigt locking):

public class Concurrent<T> {
    private ManualResetEvent _resetEvent;
    private T _result;

    public Concurrent(Func<T> f) {
        ThreadPool.QueueUserWorkItem(_ => {
                                         _result = f();
                                         IsCompleted = true;
                                         if (_resetEvent != null)
                                             _resetEvent.Set();
                                     });
    }

    public WaitHandle WaitHandle {
        get {
            if (_resetEvent == null)
                _resetEvent = new ManualResetEvent(IsCompleted);
            return _resetEvent;
        }

    public bool IsCompleted {get; private set;}
    ...

Es hat WaitHandle (träge erstellt, ebenso wie in IAsyncResult Dokumentation beschrieben) und IsCompleted, aber ich weiß nicht, eine vernünftige Implementierung für AsyncState sehen ({return null;}?). So macht es Sinn für sie IAsyncResult zu implementieren? Beachten Sie, dass Task in den Parallel Extensions Bibliothek IAsyncResult nicht implementiert, aber nur IsCompleted implizit umgesetzt werden.

War es hilfreich?

Lösung

  • Nach meiner Erfahrung nur anrufen EndInvoke ohne entweder warten oder wieder zuerst genannt wird, ist selten sinnvoll
  • Just Rückrufe Bereitstellung ist manchmal nicht genug, wie Sie Ihre Kunden für mehrere Operationen gleichzeitig (WaitAny, WaitAll)
  • warten möchten
  • Ich habe noch nie IsCompleted abgefragt, igitt in der Tat! So könnten Sie die Implementierung von IsCompleted zu sparen, aber es ist so einfach, dass es nicht wert zu sein scheint, um potenziell Ihre Kunden verblüffen.

Also, eine vernünftige Implementierung für eine asynchron aufrufbaren Methode wirklich vollständig umgesetzt IAsyncResult bieten sollte.

BTW, müssen Sie oft nicht implementieren IAsyncResult selbst, nur zurückgeben, was von Delegate.BeginInvoke zurückgeführt wird. Siehe die Implementierung von System.IO.Stream.BeginRead für ein Beispiel.

Andere Tipps

Es scheint, wie Sie ein paar Fragen haben. Lassen Sie uns mit ihnen umgehen einzeln

Erstellen von Waithandle lazily

Ja, das ist der richtige Ansatz. Sie sollten in einem Thread sichere Art und Weise tun dies aber faul ist der Weg.

obwohl Der Trick ist die Entsorgung des Waithandle. Waithandle ist eine Basis von IDisposable und muss der in einer angemessenen Art und Weise entsorgt werden. Die Dokumentation für IAsycResult nicht diesen Fall abdecken. Der beste Weg, dies zu tun, ist in EndInvoke. Die Dokumentation für BeginInvoke ausdrücklich, dass für jeden BeginInvoke, muss es eine entsprechende EndInvoke (oder Beginread / EndRead). Dies ist der beste Ort, an dem der Waithandle zu entsorgen.

Wie soll umgesetzt AsyncState werden?

Wenn Sie die Standard-BCL-API suchen, die eine IAsyncResult zurückkehren, nehmen die meisten von ihnen einen Zustandsparameter. Dies ist normalerweise der Wert, der von AsyncState (siehe die Socket-API für ein Beispiel) zurückgeführt wird. Es ist eine gute Praxis, eine Zustandsvariable als Objekt für jeden API BeginInvoke Stil API getippt umfasst, die eine IAsyncResult zurück. Nicht notwendig, aber gute Praxis.

Im abscence einer Zustandsvariablen, null zurückkehrt, ist akzeptabel.

IsCompleted API

Dies wird stark abhängig von der Implementierung, die die IAsyncResult schafft. Aber ja, sollten Sie es implementieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top