2011-01-07 11 views
26

Ich habe ClientBase implementiert, um WCF für die Verbindung mit einem Dienst zu verwenden. Ich rufe dann eine Methode auf dem Kanal an, um mit dem Dienst zu kommunizieren.Ist WCF ClientBase threadsicher?

Ist dieser Aufruf Thread sicher oder sollte ich ihn sperren, wenn mehrere Threads ausgeführt werden?

Dank

Antwort

3

Ja, um das Verfahren auf dem Kanal Aufruf threadsicher (von der Client-Sicht - service Perspektive hängt von Service-Implementierung). Sie können diese Methode aus mehreren parallelen Threads aufrufen. Selbst der automatisch generierende Proxy bietet Ihnen die Möglichkeit, Methoden für asynchrone Aufrufe zu erstellen.

+1

Objekt Was ist Ihr Beweis oder Grund zu sagen, dass es Thread-sicher ist? Ich frage, weil das Ende [der ClientBase-Klasse auf MSDN] (http://msdn.microsoft.com/en-us/library/ms576141%28v=vs.110%29.aspx) es sagt, dass es nicht ist fadensicher. – ChrisW

+0

@ChrisW: Das bedeutet wahrscheinlich, dass der Zugriff auf Eigenschaften von 'ClientBase' nicht Thread-sicher ist, aber der Aufruf zum Dienst ist (oder es kann ein Fehler in der Dokumentation sein - das ist nicht so selten). Zunächst einmal können Sie ohne Kundenbasis telefonieren - Sie brauchen nur einen Kanal. Ich habe keine Beweise. Ich glaube nur, dass das Anrufen von Remotediensten keine globalen gemeinsamen Daten speichern muss - ansonsten wäre die gesamte Clientseite von WCF schrecklich schlecht gestaltet. –

+0

Ist der innere "Kanal" als threadsicher bekannt? Ich stelle mir vor, dass ein Kanal einige Speicherpuffer und einen Netzwerk-Socket besitzt; und dass, es sei denn, dass es explizit entworfen wurde, um gleichzeitige Benutzer zu unterstützen (z. B. durch Sequenzieren ihrer Anforderungen), es katastrophal wäre, wenn zwei versuchen, gleichzeitig in den Speicher und den Socket zu schreiben. – ChrisW

10

Ja, es ist Thread-Safe. Sie sollten jedoch wissen, dass WCF die Ausführung von CalculateSomething automatisch serialisiert, wenn sie von mehreren Threads mit der gleichen ClientBase Instanz aufgerufen wird. Wenn Sie also erwarten, dass CalculateSomething gleichzeitig ausgeführt wird, müssen Sie Ihr Design überdenken. Werfen Sie einen Blick auf this answer für einen Ansatz zum Erstellen einer asynchronen API für die CalculateSomething-Methode.

+2

Können Sie erklären, was Sie meinen: "Sie sollten jedoch wissen, dass WCF automatisch die Ausführung von CalculateSomething serialisieren wird, wenn es von mehreren Threads aufgerufen wird, die die gleiche ClientBase-Instanz verwenden." Vielen Dank! – Erick

+4

Es bedeutet, dass WCF die Aufrufe der Reihe nach nacheinander und nicht gleichzeitig ausführt (obwohl dies aus programmatischer Sicht so aussieht). –

+1

Was ist Ihr Beweis oder Grund zu sagen, dass es Thread-sicher ist? Und woher wissen Sie, dass CalculateSomething automatisch serialisiert wird: Wird es von der clientseitigen ClientBase-Instanz oder auf der Server/Implementierungsseite serialisiert? Ich frage, weil das Ende [der ClientBase-Klasse auf MSDN] (http://msdn.microsoft.com/en-us/library/ms576141%28v=vs.110%29.aspx) es sagt, dass es nicht ist fadensicher. – ChrisW

14

Die Follow-up-Kommentare zu den Antworten hier hatten mich auch unsicher, also habe ich noch mehr gegraben. Hier sind einige konkrete Hinweise, dass ClientBase<T> threadsicher ist - this blog post beschreibt, wie einem WCF-Dienst machen richtig ausführen in Gegenwart von ein einzelner Client-Proxy von mehreren Threads benutzt wird gleichzeitig (die fett Betonung liegt im Original):

... Allerdings gibt es ein Szenario, in dem auf einem PerCall Service ConcurrencyMode auf mehrere Einstellung kann den Durchsatz zu Ihren Diensten erhöhen, wenn folgende Bedingungen gelten:

  1. Der Client ist multi-threaded und ruft Ihren Dienst aus mehreren Threads mit dem gleichen Proxy.

  2. zwischen dem Client und dem Dienst Die Bindung ist eine Bindung, die Sitzung (beispielsweise netTcpBinding, wsHttpBinding w/Reliable Session, NetNamedPipeBinding, etc.) hat.

Auch die Beweise in diesem Beitrag scheint Brians zusätzliche Bemerkung, dass WCF serialisiert alle Multi-Threaded-Anforderungen zu widersprechen. Der Post zeigt mehrere Anforderungen von einem einzelnen Client unter gleichzeitig - , wennConcurrencyMode.Multiple und InstanceContextMode.PerCall verwendet werden.

Es gibt einige zusätzliche Diskussion here in Bezug auf die Auswirkungen dieses Ansatzes auf die Leistung sowie einige Alternativen.

+1

_Während Kanäle und Clients, die von den Kanälen erstellt wurden, threadsicher sind, unterstützen sie möglicherweise nicht das gleichzeitige Schreiben von mehr als einer Nachricht an die Verbindung._ Quelle: [MS docs] (https://docs.microsoft.com/de-de/dotnet/framework/wcf/feature-details/mittlere-stufe-client-anwendungen? view = netframework-4.7.1) –

0

Wem es betrifft. WCF-Client-Basis kann Thread-sicher sein, zumindest in dieser Konfiguration. Ich habe keine anderen Konfigurationen ausprobiert.

[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IWcfCallbacksContract), Namespace = "http://wcf.applicatin.srv/namespace")] 
public interface IWcfContract 
{ 
    [OperationContract] 
    CompositeReturnObject GetServerObject(); 
} 

Service:

public CompositeReturnObject GetServerObject() 
{ 
    CompositeReturnObject ret = new CompositeReturnObject("Hello"); 
    Thread.Sleep(10000); // Simulating long call 
    return ret; 
} 

Auftraggeber:

private void GetData_Click(object sender, RoutedEventArgs e) 
{ 
    Console.WriteLine("Task 1 start: " + DateTime.Now.ToString("HH:mm:ss")); 

    Task.Factory.StartNew(() => { 
     var res = _proxy.GetServerObject(); 
     Console.WriteLine("Task 1 finish: " + DateTime.Now.ToString("HH:mm:s")); 
     Console.WriteLine(res.ToString()); 
     return; 
    } 
    ); 

    Thread.Sleep(2000); 

    Console.WriteLine("Task 2 start: " + DateTime.Now.ToString("HH:mm:ss")); 

    Task.Factory.StartNew(() => { 
     var res = _proxy.GetServerObject(); 
     Console.WriteLine("Task 2 finish: " + DateTime.Now.ToString("HH:mm:s")); 
     Console.WriteLine(res.ToString()); 
     return; 
    } 
    ); 
} 

und Ergebnis:

Aufgabe 1 Start: 15.47.08
Aufgabe 2 Beginn: 15 : 47: 10

Aufgabe 1 Oberfläche: 15.47.18
Name: Objekt ein "Hallo"

Aufgabe 2 Oberfläche: 15.47.20
Name: "Hallo" ein

+0

Dies zeigt, dass die Anrufe nicht serialisiert sind. Es konnte nicht beweisen, dass der Client Thread-sicher ist - es kann ein Zufall sein. –