2009-07-20 18 views
8

En uno de los tutoriales de WCF, vi el siguiente código de ejemplo:service.close() vs. service.abort() - WCF ejemplo

Dim service as ...(a WCF service) 

try 

    .. 

    service.close() 

catch ex as Exception() 
    ... 

    service.abort() 

end try 

es esta la forma correcta para asegurar que los recursos (es decir, conexiones) se liberan incluso en condiciones de error?

Respuesta

4

he tenido buena suerte con este modelo:

Dim service As New MyService() 
Dim closed As Boolean = False 
Try 
    service.Open() 
    If Not service.State = ServiceModel.CommunicationState.Opened Then 
     ''Handle a not-opened state here 
    End If 
    service.MyMethod() 
    service.Close() 
    closed = true 
Catch ex As Exception 
    ''Handle errors here 
Finally 
    If Not closed Then 
     service.Abort() 
    End If 
End Try 
service = Nothing 
2

Tienes la idea general correcta. He utilizado el siguiente método de extensión para mantener las líneas de código repetitivo al mínimo.

public static class ICommunicationObjectExtensions 
{  
    public static void SafelyCloseConnection(this ICommunicationObject objectToClose) 
    { 
     bool success = false; 

     try 
     { 
     objectToClose.Close(); 
     success = true; 
     } 
     finally 
     { 
     if (!success) 
     { 
      objectToClose.Abort(); 
     } 
     } 
    } 
} 

Ejemplo de código usando este método de extensión:

HelloWorldServiceClient client = new HelloWorldServiceClient(); 
HelloWorldDataContract dc = new HelloWorldDataContract(); 

try 
{ 
    client.Open(); 
    dc = client.SayHello(); 
} // Add catch blocks here for anything you want to handle. 
finally 
{ 
    client.SafelyCloseConnection(); 
} 

Por supuesto, esto es C#, pero creo que todavía debe ser de ayuda.

15

Ver indisponible: WCF Problema nº 1 *, donde se le ocurre un método de envoltura conveniente:

public delegate void UseServiceDelegate<T>(T proxy); 

public static class Service<T> 
{ 
    public static ChannelFactory<T> _channelFactory = new ChannelFactory<T>(""); 

    public static void Use(UseServiceDelegate<T> codeBlock) 
    { 
     var proxy = (IClientChannel)_channelFactory.CreateChannel(); 
     var success = false; 
     try 
     { 
      codeBlock((T)proxy); 
      proxy.Close(); 
      success = true; 
     } 
     finally 
     { 
      if (!success) 
      { 
       proxy.Abort(); 
      } 
     } 
    } 
} 

Uso:

Service<IOrderService>.Use(
    orderService => 
     { 
      orderService.PlaceOrder(request); 
     }); 

* Enlace eliminado, ya que parece ser malicioso .

+0

Me gusta su solución, pero ¿tiene uno, que se puede usar con Dependency Injection. Como un servicio es una dependencia, no quiero ejecutar mi prueba en su contra. –

+0

No es mi solución. En cualquier caso, espero que pueda hacer 'Service ' no estático, e inyecte 'ChannelFactory ', o 'IClientChannel'. –

0

Si utiliza una memoria caché del lado del cliente, es posible considerar el uso de los árboles de expresión (véase http://thegrenade.blogspot.com/2009/07/using-expression-trees-for-more-elegant.html):

private static TEntity GetItem<TProxy, TEntity, TIdentity>(Expression<Func<TProxy, TIdentity, TEntity>> expression, TProxy proxy, TIdentity id) 
    where TEntity : class 
    where TProxy : ICommunicationObject 
{ 
    TEntity item = Cache.GetItem<TEntity, TIdentity>(id); 
    if (item == null) 
    { 
     try 
     { 
      var originalDelegate = expression.Compile(); 
      item = originalDelegate.Invoke(proxy, id); 
     } 
     finally 
     { 
      try{ proxy.Close(); } 
      finally { proxy.Abort(); } 
     } 
     Cache.AddItem<TEntity, TIdentity>(item); 
    } 
    return item; 
} 

Uso:

Product p = GetItem((client, identifier) => client.GetProduct(identifier), new CatalogServiceClient(), 123); 
+0

Rob, no veo cómo se aplica tu respuesta a esta pregunta. –

+0

Tal vez el ejemplo de método que he dado es demasiado específico para un contenedor genérico de llamadas de servicio. De hecho, necesita sobrecargas de método para los métodos de servicio que toman más de un parámetro y este ejemplo no entra en ese detalle. Sin embargo, muchas soluciones WCF contienen grupos de métodos muy similares que simplemente devuelven diferentes tipos en respuesta a un get con un parámetro id. Y estás en lo cierto al decir que mi bloque final también falta un try anidado/finalmente para el aborto. – grenade

+0

Creo que es posible que deba volver a leer la pregunta. Su respuesta no aborda la pregunta de ninguna manera. –