2011-01-07 16 views
26

Ho implementato ClientBase per utilizzare WCF per connettersi a un servizio. Sto quindi chiamando un metodo sul canale per comunicare con il servizio.Il thread WCF ClientBase è sicuro?

base.Channel.CalculateSomething(); 

Questo thread di chiamate è sicuro o è necessario bloccarlo quando si eseguono più thread?

Grazie

risposta

3

Sì chiamando il metodo sul canale è thread-safe (dal punto di vista del cliente - prospettiva di servizio dipende dalla implementazione del servizio). È possibile chiamare questo metodo da più thread in parallelo. Anche il proxy di auto-generazione ti offrirà la possibilità di creare metodi per le chiamate asincrone.

+1

Che cosa è la tua prova o ragione per dire che è thread-safe? Sto chiedendo perché la fine della [classe ClientBase su MSDN] (http://msdn.microsoft.com/en-us/library/ms576141%28v=vs.110%29.aspx) dice che non è thread-safe. – ChrisW

+0

@ChrisW: Questo probabilmente significa che l'accesso alle proprietà di 'ClientBase' non è thread-safe ma la chiamata al servizio è (o può essere un bug nella documentazione - che non è così raro). Prima di tutto è possibile effettuare una chiamata senza base client - è sufficiente un canale. Non ho alcuna prova. Credo solo che chiamare il servizio remoto non abbia bisogno di memorizzare alcun dato globale condiviso - altrimenti l'intero lato client di WCF sarebbe terribilmente mal progettato. –

+0

Il "canale" interno è noto per essere thread-safe? Immagino che un canale possieda alcuni buffer di memoria e un socket di rete; e che, a meno che non sia progettato esplicitamente per supportare utenti concorrenti (ad esempio sequenziando le loro richieste), sarebbe disastroso se due provassero a scrivere contemporaneamente nella memoria e nel socket. – ChrisW

10

Sì, è thread-safe. Tuttavia, dovresti sapere che WCF serializzerà automaticamente l'esecuzione di CalculateSomething quando viene chiamata da più thread utilizzando la stessa istanza ClientBase. Quindi se ti aspettavi di eseguire CalculateSomething contemporaneamente dovresti riconsiderare il tuo design. Dai un'occhiata a this answer per un approccio alla creazione di un'API asincrona per il metodo CalculateSomething.

+2

Puoi spiegare cosa intendi con: "Tuttavia, dovresti sapere che WCF serializzerà automaticamente l'esecuzione di CalculateSomething quando viene chiamata da più thread utilizzando la stessa istanza di ClientBase." Grazie! – Erick

+4

Significa che WCF effettuerà le chiamate una dopo l'altra, in modo sequenziale, e non simultaneamente (sebbene sembrino essere fatte così da un punto di vista programmatico). –

+1

Qual è la tua prova o la ragione per dire che è thread-safe? E come fai a sapere che CalculateSomething viene serializzato automaticamente: è serializzato dall'istanza ClientBase lato client o dal lato server/implementazione? Sto chiedendo perché la fine della [classe ClientBase su MSDN] (http://msdn.microsoft.com/en-us/library/ms576141%28v=vs.110%29.aspx) dice che non è thread-safe. – ChrisW

14

Anche i commenti di follow-up sulle risposte qui mi hanno incerto, quindi ho scavato un po 'di più. Ecco alcune prove solide che ClientBase<T> è thread-safe - this blog post discute come fare un servizio WCF funziona correttamente in presenza di un unico proxy client viene utilizzato da più thread contemporaneamente (l'enfasi grassetto è nell'originale):

... Tuttavia, v'è uno scenario in cui l'impostazione ConcurrencyMode ad multipla su un servizio PerCall può aumentare il throughput al vostro servizio, se si applicano le seguenti condizioni:

  1. Il cliente è multi-threaded e sta effettuando chiamate al tuo servizio da più thread utilizzando lo stesso proxy.

  2. Il legame tra il client e il servizio è un legame che ha sessione (ad esempio, netTcpBinding, wsHttpBinding w/affidabile Session, netNamedPipeBinding, etc.).

Inoltre, le prove in questo post sembra contraddire nota aggiuntiva di Brian che WCF serializza eventuali richieste multi-threaded. Il post mostra più richieste da un singolo client in esecuzione contemporaneamente - se vengono utilizzatiConcurrencyMode.Multiple e InstanceContextMode.PerCall.

C'è qualche discussione aggiuntiva here riguardante le implicazioni di prestazione di questo approccio così come alcune alternative.

+1

_Che i canali e i client creati dai canali sono sicuri per i thread, potrebbero non supportare la scrittura simultanea di più messaggi sul filo. S Fonte: [MS docs] (https://docs.microsoft.it/it-it/dotnet/framework/wcf/feature-details/middle-tier-client-applications? view = netframework-4.7.1) –

0

A chi può interessare. La base del client WCF può essere thread-safe, almeno in questa configurazione. Non ho provato altre configurazioni.

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

Servizio:

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

Cliente:

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; 
    } 
    ); 
} 

E risultato:

Task 1 inizio: 15:47:08
Task 2 inizio: 15 : 47: 10

Task 1 finitura: 15:47:18
Nome: oggetto "Ciao"

Task 2 finitura: 15:47:20
Nome: oggetto "Ciao"

+0

Questo mostra che le chiamate non sono serializzate. Non è stato possibile dimostrare che il client è sicuro per il thread: potrebbe essere una coincidenza. –