WCF-client-Deadlocks aufgrund callback-auch wenn callback IsOneWay
neuen WCF.
Ich habe einen client, der Deadlocks beim Aufruf einer WCF-Dienst.
Den service aufrufen, die einen Rückruf an den client an der Uhrzeit des Anrufs, die gekennzeichnet ist als IsOneWay. Ich habe bestätigt, dass der Dienst nicht blockiert, auf den Rückruf.
Client ruft sofort den gleichen service wieder (in einer engen Schleife), ohne doch den Rückruf gewartet. Der client wird dann von deadlocks (und einen Haltepunkt auf der service-Seite wird nie ausgelöst).
So zur Erinnerung:
CLIENT SERVICE
Call service -----------------------> (service breakpoint triggers)
(waiting for dispatch thread) <------ Invoke callback (IsOneWay - doesn't block)
Service returns
Call service again immediately -----? (service breakpoint doesn't trigger)
(deadlock)
Gehe ich davon aus, dass der Rückruf hat packte einige WCF-Sperre auf der client-Seite, und dann die zweite service-Aufruf von der client-will auch, dass sperren, so deadlock Ergebnisse. Aber das ist nur Vermutung.
Ich gelesen habe ConcurrencyMode aber ich kann mich nicht entscheiden, welcher Modus zu verwenden ist, oder wo es, da bin ich mir nicht 100% klar, was Los ist, und was blockiert wird, genau.
Ich würde auch lieber halten Sie alle Rückrufe, die verarbeitet werden, indem die dispatch-thread wenn möglich, wie es hält den code einfacher.
Kann ein WCF-Experten ein Licht auf genau das, was ist hier Los?
Vielen Dank
- Können Sie zeigen Sie uns den code?
- Kaum Wert, es gibt nichts zu es. Es ist eher ein problem von mir zu verstehen, wie WCF befasst sich mit und synchronisiert Rückrufe.
- Welche Art der client-Anwendung haben Sie? Sind sowohl client-als auch call-und callback-Wege, oder einer von Ihnen mit der Antwort?
Du musst angemeldet sein, um einen Kommentar abzugeben.
OK, ich glaube ich habe es sussed es.
WCF-Dienste, die standardmäßig auf single threaded. Alle Anrufe und Rückrufe bekommen gemarshallt, um einen einzelnen thread (oder SynchronizationContext um genauer zu sein).
Meine app ist eine single-threaded-WPF-Anwendung, so dass die SynchronizationContext-festgelegt wird, um die dispatch-thread.
Wenn der Rückruf kommt, in der er versucht, Marschall der Aufruf der dispatch-thread, das ist natürlich sa-Blockierung auf der original-service-Aufruf. Ich bin mir nicht klar, es sperrt genau, aber es gibt offensichtlich einige Globale Sperre, die es versucht, sich vor dem warten auf die dispatch-thread.
Wenn der dispatch-thread ruft dann den service wieder, es deadlocks auf diese Globale Sperre.
Zwei Möglichkeiten um ihn herum:
1) Erstellen Sie den service-proxy auf einem anderen thread in den ersten Platz. Alle Anrufe erhalten gemarshallt über diesen thread statt-und es wird nicht egal, dass der dispatch-thread blockiert ist.
2) [CallbackBehavior(UseSynchronizationContext = false)] - Attribut der client-Klasse implementiert die callback. Dies bedeutet WCF ignorieren die synchronisation Kontext, wenn der Rückruf kommt, und es wird der service auf jedem verfügbaren thread.
Ging ich mit 2. Offensichtlich bedeutet dies, ich muss Marschall Rückrufe, könnte ein update des GUI, um die dispatch-thread selbst, aber zum Glück ist meine callback-Implementierung ist ein kleiner wrapper, wie auch immer, ich mache nur einen _dispatcher.BeginInvoke() in jedem callback-Methode marshal ASYNCHRON. Der dispatch-thread wird dann service, wenn Sie eine chance bekommt, die ist, was ich wollte in den ersten Platz.
SynchronizationContext
auf dieInstanceContext
verwendet, um dasDuplexChannelFactory
. Wenn er auf einer Ebenenew SynchronizationContext()
funktioniert einwandfrei.Der Reihenfolge, in der Sie dargestellt, ähnelt einem synchronen Aufruf. Während in der einen asynchronen Aufruf, die Reihenfolge wäre:
In jedem Fall von jedem asynchronen web-service-Aufruf, erzeugt das system einen separaten IO-thread(IOCP-thread), und verarbeitet die Anfrage. In diesem, nur selten finden Sie eine Sackgasse.
Habe ich so gefunden, auch wenn der Aufruf innerhalb einer Schleife zu arbeiten, sehr gut.
Können Sie, zum Beispiel, für die Veranstaltung anmelden
.OnProcessComplete
, und rufen Sie dann dieProcessCompleteAsync
Methode.ProcessRequest(1)
wird die push-operation an eine Warteschlange, und ein thread wirdDequeue
ein Element, zu verarbeiten und zu reagieren. Oder enqueue-fordert, um einethreadpool
worker-threads, die direkt von der WCF-Betrieb mit asynchronen Delegaten; und gesetztthreadpool
basierte Zeitgeber aus Ihrer WCF-Betrieb.