2016-07-09 12 views
2

ich das noch nicht gesehen haben, antwortete ziemlich einfache Einrichtung ...WCF einen Dienst von einem Dienst aufrufen

Frage: Ich bin ein Deadlock bekommen, möchte ich wissen, wie es zu vermeiden, da mein Setup .

Ich habe ServiceA, die IServiceA und ServiceB implementiert, die IServiceB implementiert. Beide Dienste werden als "PerSession" und "einspringenden" gekennzeichnet ...

IServiceA unterstützt diese Methode:

DataA GetDataA(); 

IServiceB unterstützt diese Methode:

DataB GetDataB(); 

in meiner app, ich Aufruf ServiceA GetDataA() Methode, und in ServiceA's GetDataA-Methode, es öffnet eine Proxy-Verbindung zu ServiceB und ruft GetDataB().

GetDataB am Service-Ende (nicht am Ende des Clients) wird korrekt ausgeführt (das Debug-Protokoll sagt dies), aber wenn es versucht, die Daten an ServiceA zurückzugeben, wird es deadlocks.

Ich nehme an, das ist, weil, wenn ich in ServiceA von "Benutzer" rief, er die IO-Abschluss-Port "Lieferung Sperre" (oder vielleicht ist es WCF pro Sitzung "Sperre. Auf jeden Fall eine Sperre Ich nehme an, dass, wenn ServiceB's GetDataB() versucht, den Wert zurückzugeben, was ist es wirklich getan ist um den Kanal herum und versucht, eine Empfangsmethode auf ServiceA, die die Sperre und Deadlocks benötigt, die die Sperre und Deadlocks benötigt Jede Frage, die ich bisher gelesen habe, wo die Leute fragen "ist es in Ordnung, einen Dienst von einem anderen zu ketten", war jede (dumme) Antwort "sicher! mach weiter! nichts dran! Dienste wissen nicht, ob sie es sind durch normalen .NET-Code aufgerufen werden oder wenn sie von einem anderen Dienst angerufen werden! ". Ärgerlich. Es gibt sicherlich" einige Ding dazu ", auch wenn es ein kleines bisschen trivial ist.

Ich habe gelesen, dass ich Methoden nicht markieren kann, die Werte als "Einweg" zurückgeben. Und sie als "Wiedereinsteiger" zu markieren ... sollte das funktionieren oder nicht? Ich weiß, wenn ich in meinem Dienst einen Rückruf rufe, wird die Sperre stillgelegt. Was ist, wenn ich einen anderen Dienst anrufe? ist WCF intelligent genug, um auch in diesem Fall das Schloss freizugeben?

Ich könnte meine Dienste als "multiple" anstelle von "re-entrant" markieren, aber ich frage mich (a) ist der Deadlock wirklich von dem, was ich denke, oder könnte es von etwas anderem sein, und (b) Gibt es einen besseren Weg dazu?

+0

Die "dummen" Antworten, die Sie gesehen haben, sind so, weil das Verketten von Serviceaufrufen (normalerweise) einfach nur "dumm" einfach ist. Es muss etwas anderes zu deinem speziellen Fall geben. Haben Sie [WCF trace] (http://stackoverflow.com/a/4271597/21567) aktiviert/angeschaut? Vielleicht möchten Sie mehr (technische) Informationen zu Ihrem Setup bereitstellen (Code, Konfiguration usw.). –

+0

Natürlich können Sie Service-Anrufe von anderen Diensten ketten, ich habe es viele, viele Male getan. Vielleicht, wenn Sie Ihren Code auf Github hosten könnten (oder ihn zumindest mit einer Demo-App neu erstellen, die das Problem nachbildet) oder etwas, könnte es den Leuten einen besseren Kontext geben, mit was Sie arbeiten, um Ihnen zu helfen. Es scheint, dass Sie ein spezielles Schneeflockenszenario erreicht haben oder etwas falsch konfiguriert wurde, wer weiß. –

+0

also ... der Deadlock "sollte nicht passieren"? Wenn der Stack-Pointer momentan in der GetDataA() -Methode von ServiceA ist und ich die GetDataB() -Methode von ServiceB aufruft und GetDataB() ausführt und versucht, mich mit den resultierenden Daten zurückzurufen, sollte es nicht durch das Versuch Deadlocking sein die Empfangssperre in ServiceA? Ich habe eine Test-App geschrieben, um dies zu demonstrieren, eine mit zwei Diensten, und ich bin überrascht, dass ich es NICHT festgefahren sehe, aber ich kann nicht herausfinden, warum es nicht festgefahren ist. Sollte es nicht sein? Wenn B versucht, die Daten an A zurückzugeben, sollte es nicht versuchen, eine Sperre zu erhalten und fehlschlagen? –

Antwort

1

Ich habe es herausgefunden. Und ich ehrlich sein muss, begann ich WCF Lernen von MSDN lesen, aber es dröhnte weiter und weiter, so zog ich nach einigen WCF Online-Bücher auf (von Lowy & andere). Ich hätte MSDN lesen sollen.

bekam ich diese Antwort von einem des Entwicklers auf dem WCF-Team:

„Das Schloss ist nicht passiert auf der Transportschicht, ist es an der Instanz-Kontext Schicht geschieht Wenn ein Client in Dienst A eine macht. Ausgehende Anfrage-Antwort-Anruf an Dienst B, die Antwort geht nicht zurück zu Dienst A, es geht zurück zum Client für Dienst B, den Dienst A verwendet. "

Das macht Sinn. Aber zusätzlich zu dieser Information habe ich auch Folgendes gelernt:

"Wenn Sie WCF-Dienste verwenden, um aus einer beliebigen Methode (CallOut = Rückruf oder einen anderen WCF-Dienst) aufzurufen, und Sie sind als" ReentTransent ", WCF markiert wird das InstanceLock freigeben ".

(also aus der Sackgasse ich oben gesehen habe, ist (wahrscheinlich) meine eigene Schuld ...)

ich diesen tidbit hier:

https://channel9.msdn.com/Forums/TechOff/254330-WCF-ConcurrencyModeReentrant-Confusion

Und das führte mich zu diesem wertvolle Artikel hier:

https://msdn.microsoft.com/en-us/library/aa395214(v=vs.110).aspx

Zitat: Bei Reentrante Modus, der InstanceContext ist unlocke d kurz bevor der Dienst einen AUSGEHENDEN ANRUF tätigt, wodurch der nachfolgende Anruf (der wie im Beispiel gezeigt wiedereinwechseln kann) die Sperre erhält, wenn er das nächste Mal zum Dienst kommt.