2010-04-10 15 views
7

Al invocar un servicio WCF asincrónico, parece que hay dos maneras de hacerlo.¿Qué modo se prefiere cuando se realizan llamadas WCF asíncronas?

1.

WcfClient _client = new WcfClient();  
public void One() 
{ 
    _client.BegindoSearch("input", ResultOne, null); 
} 

private void ResultOne(IAsyncResult ar) 
{ 
    string data = _client.EnddoSearch(ar); 
} 

2.

public void Two() 
{ 
    WcfClient client = new WcfClient(); 
    client.doSearchCompleted += TwoCompleted; 
    client.doSearchAsync("input"); 
} 

void TwoCompleted(object sender, doSearchCompletedEventArgs e) 
{ 
    string data = e.Result; 
} 

Y con la nueva clase Task<T> tenemos una tercera forma fácil envolviendo el funcionamiento síncrono en una tarea.

3.

public void Three() 
{ 
    WcfClient client = new WcfClient(); 
    var task = Task<string>.Factory.StartNew(() => client.doSearch("input")); 
    string data = task.Result; 
} 

Todos ellos le dan la capacidad de ejecutar otro código mientras espera el resultado, pero creo que Task<T> da un mejor control sobre lo que se ejecuta antes o después de que el resultado se recupera .

¿Hay alguna ventaja o desventaja al usar una sobre la otra? ¿O escenarios donde una forma de hacerlo es más preferible?

Respuesta

5

No usaría no utilice la versión final porque ejecutará la operación en un subproceso de trabajo en lugar de un subproceso de E/S. Esto es especialmente malo si lo hace dentro de ASP.NET, donde los hilos de trabajo son necesarios para atender las solicitudes. Sin mencionar, todavía estás bloqueando el hilo principal esperando a que la tarea finalice cuando marques su Result, por lo que técnicamente estás desperdiciando dos hilos de trabajo, o un trabajador y la IU.

Los métodos BeginXYZ y XyzAsync para clientes WCF funcionan básicamente de la misma manera: debe elegir la versión adecuada según el caso de uso que desee admitir (ya sea APC o controlado por evento, respectivamente). Por ejemplo, la versión BeginXyz sería (quizás contra intuitiva) más fácil de usar dentro de una página asíncrona ASP.NET (o MVC), mientras que la versión XyzAsync sería más fácil de usar en un Windows Form.

+0

El aspecto del subproceso Trabajador vs IO es interesante. Sé que el grupo de subprocesos tiene una cantidad fija de cada uno y que puede cambiarlos. Pero cuál es la diferencia entre un subproceso de trabajo y subproceso de E/S en el marco. Supongo que es más que solo semántica. –

+0

@Mikael: los hilos de E/S están diseñados para largos períodos de espera; básicamente se van a dormir y esperan a que el sistema de E/S los vuelva a activar con una interrupción. Los subprocesos de trabajo están pensados ​​para el trabajo pesado de la CPU, y no desea desperdiciarlos al bloquear las llamadas de E/S sincrónicas. – Aaronaught

+0

hay más información en este artículo de MSDN sobre las tareas con respecto a los subprocesos de trabajo: http://msdn.microsoft.com/en-us/magazine/ff959203.aspx, también un buen fondo (una clase de lección de historia) sobre el diferentes métodos asíncronos disponibles en.NET –

2

Hay un problema con su primer ejemplo. Ciertamente debe no crear una nueva instancia de WcfClient cuando llame a EndDoSearch. Debe mantener la instancia original en un campo o pasarla como parámetro de estado.

Pero, en general, prefiero la opción n. ° 1 porque hace que sea muy fácil usar un método anónimo para manejar el resultado.

var client = new WcfClient(); 
client.BeginDoSearch("input", ar => { 

    var result = client.EndDoSearch(ar); 
    // blah blah 

}, null); 
+0

Buena captura en eso; tenga en cuenta que es dudoso crear el período * de los clientes de WCF *; por lo general, estos terminan siendo únicos/por sesión o administrados por un contenedor DI. – Aaronaught

+0

@Josh, sé que debería usar el mismo cliente y lo he corregido ahora :) –

Cuestiones relacionadas