Wir haben eine Anwendung (Konsolenanwendung "Server", die eine Reihe von WCF-Diensten und ein paar WPF-Clients hostet), die in .NET 3.5 geschrieben sind. Ich wollte versuchen, die "Server" -App auf .NET 4.6 zu aktualisieren. Zum Testen wollte ich nur die Laufzeit ändern und einige untergeordnete Projekte in 4.6 hinzufügen, während der Rest der Projekte bei 3.5 bleibt. Im Top-Level-Projekt habe ich das Ziel auf 4.6 geändert und dafür gesorgt, dass die Datei app.config folgendes enthielt:
%Vor%Die WCF-Dienste und andere Unterstützungsprojekte sind in der Lösung und ich habe sie auf keinen Fall geändert.
Ich habe auch den WPF-Client nicht geändert.
In einigen unserer Dienste implementieren wir das asynchrone Anfangs- / Ende-Muster auf dem Server . Das ist neu für mich, da ich WCF mit dem async / await-Muster gelernt habe (obwohl ich allgemein mit Beginn / Ende vertraut bin). Alle asynchronen Anforderungen auf dem Client bleiben dem aufrufenden Code überlassen.
Service
%Vor%Client (wie von Visual Studio "Service-Referenz hinzufügen" generiert)
%Vor%Auf dem Client gibt es einige generische Klassen, die unsere Dienste umhüllen und offen legen. Aufrufe können auf dem Hauptthread stattfinden, sind aber normalerweise auf Hintergrundthreads über Hintergrundarbeiter. Wenn Sie einfach die Server-App von .NET 3.5 auf 4+ aktualisieren und keine Änderungen vornehmen, werden die End-Methoden auf dem Server nicht mehr aufgerufen. Ich habe bestätigt, dass die Begin-Methoden zurückgegeben werden und die Worker ".Complete ()" aufrufen und den Callback aufrufen. Danach geschieht jedoch nichts. Nach 1 Minute wird der Client eine Timeout-Ausnahme für den Anruf auslösen.
Unsere Codebasis ist ziemlich groß und komplex und ich habe nach dem Lesen der .NET 4-Migrationsnotizen keine Verhaltensänderungen erwartet.
BEARBEITEN: Ich habe einen Screenshot des microsoft service trace-Dienstprogramms mit demselben Aufruf von FetchProductVersion vor der Aktualisierung (oben, 3.5) und nachher (unten, 4.6) eingefügt.
EDIT 2/3: Die Fehler scheinen in einigen Fällen inkonsistent zu sein.
Sie müssen IAsyncResult.CompletedSynchronously
Eigenschaft zu false
, weil Sie IAsyncResult
asynchron abschließen. Im Gegensatz zu WCF in .NET Framework 4.6 ignoriert WCF in .NET Framework 3.5 es in diesem Fall einfach.
Ändern Sie also something.Complete(true);
in something.Complete(completedSynchronously: false);
.
Sie können überprüfen, wer und wann IAsyncResult.CompletedSynchronously
verwendet, indem Sie einen Haltepunkt in den Getter eingeben:
Wenn Sie den WCF-Dienst mit .NET Framework 3.5 starten, werden Sie feststellen, dass er nie tatsächlich aufgerufen wird. So ältere Version von WCF ignoriert es einfach. Wenn Sie den Dienst mit .NET Framework 4.6 starten, werden Sie feststellen, dass er von der internen WCF-Klasse DispatchOperationRuntime
ziemlich häufig verwendet wird. Von InvokeBegin()
und InvokeCallback()
funktioniert insbesondere.
Ich sehe zwei niedrig hängende Gegenstände, die Sie überprüfen sollten, bevor Sie sehr tief graben.
WCF leitet eingehende Nachrichten automatisch an Begin & lt; MethodName & gt; Methode und routet die Ergebnisse des Endes & lt; MethodName & gt; Rufen Sie die ausgehende Nachricht an.
In Ihrem Pseudocode folgen sie nicht der obigen Namenskonvention:
%Vor%
Bestätigen Sie, dass Sie Ihre Methoden entsprechend dekorieren. MSDN bietet das folgende Beispiel:
%Vor%In Ihrem Pseudocode fehlen die Attribute von OperationContract. Hoffentlich ist es so einfach. Viel Glück!