service.close() vs. service.abort() - WCF example

2019-01-22 09:51发布

In one of the WCF tutorials, I saw the following sample code:

Dim service as ...(a WCF service )

try

   ..

   service.close()

catch ex as Exception()
  ... 

   service.abort()

end try

Is this the correct way to ensure that resources (i.e. connections) are released even under error conditions?

4条回答
仙女界的扛把子
2楼-- · 2019-01-22 10:20

I've had good luck with this model:

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
查看更多
地球回转人心会变
3楼-- · 2019-01-22 10:21

See Indisposable: WCF Gotcha #1*, where he comes up with a convenient wrapper method:

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

Usage:

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

* Link removed as it appears to be malicious.

查看更多
beautiful°
4楼-- · 2019-01-22 10:32

You've got the general idea correct. I've used the following extension method to keep the lines of repetitive code to a minimum.

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

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

Example of code using this extension method:

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

Of course this is C#, but I think that should still be of help.

查看更多
Root(大扎)
5楼-- · 2019-01-22 10:34

If you use a client side cache, you might consider using Expression Trees (see 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;
}

Usage:

Product p = GetItem((client, identifier) => client.GetProduct(identifier), new CatalogServiceClient(), 123);
查看更多
登录 后发表回答