在其中一个 WCF 教程中,我看到了以下示例代码:
Dim service as ...(a WCF service )
try
..
service.close()
catch ex as Exception()
...
service.abort()
end try
这是确保即使在错误条件下也能释放资源(即连接)的正确方法吗?
请参阅 Indisposable: WCF Gotcha #1 *,他提出了一种方便的包装方法:
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();
}
}
}
}
用法:
Service<IOrderService>.Use(
orderService =>
{
orderService.PlaceOrder(request);
});
* 链接被删除,因为它似乎是恶意的。
我对这个模型很幸运:
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
你的总体思路是正确的。我使用了以下扩展方法来将重复代码行减至最少。
public static class ICommunicationObjectExtensions
{
public static void SafelyCloseConnection(this ICommunicationObject objectToClose)
{
bool success = false;
try
{
objectToClose.Close();
success = true;
}
finally
{
if (!success)
{
objectToClose.Abort();
}
}
}
}
使用此扩展方法的代码示例:
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();
}
当然这是 C#,但我认为这仍然会有所帮助。
如果您使用客户端缓存,您可能会考虑使用表达式树(请参阅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;
}
用法:
Product p = GetItem((client, identifier) => client.GetProduct(identifier), new CatalogServiceClient(), 123);