2015-02-19 7 views
13

Ich bekomme die folgende Ausnahme (kann nicht zwei Vorgänge im selben Vertrag mit dem gleichen Namen Methoden ExecuteAsync und Execute) wenn der folgende Dienst aktiviert ist .Kann nicht zwei Vorgänge im selben Vertrag mit dem gleichen Namen (Async & Non) haben

[ServiceContract] 
    public interface IMyService 
    { 
     [OperationContract] 
     byte[] Execute(MyRequest request); 

     [OperationContract] 
     Task<byte[]> ExecuteAsync(MyRequest request); 
    } 

Ich denke, das macht Sinn, wenn Sie die svcutil.exe verwenden, um Ihren Dienstverweis zu erstellen, da die Task-basierten Operationen automatisch für Sie erstellt werden. Ich möchte jedoch keine Service-Referenz hinzufügen und stattdessen einfach die Standard-ChannelFactory verwenden, um den WCF-Channel zu erstellen. Gibt es eine andere Möglichkeit, dies zu tun, ohne die asynchrone Methode in etwas anderes umzubenennen? Oder muss ich die Synchronisierungsmethode auf dem Client in einer Task.Run?

+0

wcf stützt sich async, warum Sie selbst definieren, Sie erste Methode als async auf Client –

+0

@EhsanSajjad nennen kann - svcutil.exe manchmal beides erzeugen. – StingyJack

Antwort

6

Hier ist was ich getan habe. Ich habe zwei separate Verträge. Eine für den Kunden und eine für den Server:

namespace ServiceLibrary.Server 
{ 
    [ServiceContract] 
    public interface IMyService 
    { 
     [OperationContract] 
     byte[] Execute(MyRequest request); 
    } 
} 

namespace ServiceLibrary.Client 
{ 
    [ServiceContract] 
    public interface IMyService : Server.IMyService 
    { 
     [OperationContract] 
     Task<byte[]> ExecuteAsync(MyRequest request); 
    } 
} 

Da beide Servicecontracts den gleichen Namen aufweisen, sind die OperationContracts' Aktion und ReplyAction das gleiche für die Asynchron-und Sync-Methoden. Der Client verfügt jetzt über die Synchronisierungs- und die Async-Version und der Server bleibt unverändert.

+1

Ihre Antwort auf Ihre Frage ist nicht korrekt, auch wenn sie es ist habe für dich gearbeitet, überprüfe die Antworten von JeroenMostert und @EhsanSajjad. – Gouda

+1

@Gouda Ich muss dir nicht zustimmen. Obwohl Jeroen und Ehsan praktikable Lösungen lieferten, entsprachen sie nicht meinen Anforderungen.Ich wollte keinen Thread auf dem Client verschwenden, ich wollte nicht svcutil.exe verwenden, und ich wollte die Server-Seite nicht berühren und sie synchron lassen. Wenn Sie nicht bemerkt haben, dass meine Antwort mit 3 anderen verschiedenen SO-Fragen verknüpft wurde. So sieht es aus, als ob ich nicht der einzige bin, der denkt, dass meine Antwort nicht halbwegs schlecht ist :) –

+0

+1 für diese Problemumgehung. Ich habe zuerst 'IMyServiceAsync: IMyService' im * selben * Namespace als' IMyService' erstellt, aber dies verursacht einige Laufzeitfehler bezüglich des Namenskonflikts der asynchronen Methode. Also funktionierte nur eine neue Schnittstelle mit dem gleichen Namen 'IMyService' in verschiedenen Namespaces, wie in dieser Antwort. – Sam

9

Die oben ist nicht gültig, da WCF sich für jede Operation in Ihrem Fall zwei Methoden macht Execute() eine synchrone und asynchrone zweite, die auf Client-Seite aufgerufen werden kann ServiceClientObj.ExexuteAsync(request) durch das Schreiben, so dass Sie nicht brauchen, um Asynchron-Methode explizit hinzufügen in der IMyService .Das Framework ist selbst verantwortlich für die Generierung async Methode jeder Operation

+6

Wenn Sie 'ChannelFactory' verwenden, wird die asynchrone Methode nicht automatisch generiert. –

5

Sie können beides angeben, aber nicht beides. WCF wird automatisch jede Methode im generierten Kanalproxy arbeiten lassen - Sie können eine Schnittstelle, die eine asynchrone Methode verwendet, mit einer Implementierung verbinden, die eine synchrone Methode verwendet, und umgekehrt.

Wenn Sie die Schnittstellendefinition über Client- und Servercode teilen wollen (was nicht unangemessen ist) und sich mit einem zufrieden geben müssen, ist Ihre beste Wette die asynchrone: Angebot nur Synchronisierung bedeutet, dass asynchrone Clients einen Thread verschwenden müssen async bedeutet nur, dass Anrufer die Wahl haben, den Thread selbst zu blockieren und zu verschwenden, wenn sie müssen. Da der Aufruf eines WCF-Dienstes E/A-Vorgänge beinhaltet, möchten Sie dem Client unbedingt die Option für Async geben, selbst wenn der Server über eine Synchronisierungsimplementierung verfügt.

+0

'Anrufer haben die Wahl, den Thread selbst zu blockieren und zu verschwenden' Leider ist es nicht so einfach, über Async zu synchronisieren, ohne Deadlocks zu haben, Ausnahmen mit'AggregateException' eingeschlossen. –

0

Versuchen Sie, den Namen in OperationMethod hinzuzufügen, um es einfacher zu machen.

[ServiceContract] 
public interface IMyService 
{ 
    [OperationContract(Name = "Service1")] 
    byte[] Execute(MyRequest request); 

    [OperationContract(Name = "Service2")] 
    Task<byte[]> ExecuteAsync(MyRequest request); 
} 
Verwandte Themen