This question already has answers here:
What is the best workaround for the WCF client `using` block issue?
(26 answers)
Closed 8 years ago.
I would like some clarity around the following (apologies in advance if this is a stupid question)
Am working on some existing code which calls a WCF service.
This code instantiates a WCF service client via an interface and performs the operations it needs i.e.:
IWCFService proxyClient = new WCFServiceClient()
However what am trying to do here is ensure the connection is closed gracefully i.e.: proxyClient.Close() etc but I cant access these seeing as its created via an interface (which just houses the operations i.e.: DoSomething())
If i instantiate as a WCF service client (and not via interface) i will be able to access the Close() & Abort calls which i can use in try{}catch{} blocks.
i.e.:
WCFServiceClient proxyClient = new WCFServiceClient()
//do some stuff..
proxyClient.Close()
Is it a simple case of adding Close() & Abort() to the interface definition and then calling these in the code which should in turn implement the WCF implementations of these?
I recently wrote an article about the correct handling of a WCF client's life cycle: Only wrapping the instantiation in a using block is not sufficient...
Have a look at http://blog.rsuter.com/?p=975
Summary: Overload Dispose the following way to use the client with the using keyword:
public void Dispose()
{
if (isDisposed)
return;
try
{
if (service.State == CommunicationState.Faulted)
service.Abort();
else
{
try
{
service.Close();
}
catch (Exception closeException)
{
try
{
service.Abort();
}
catch (Exception abortException)
{
throw new AggregateException(closeException, abortException);
}
throw;
}
}
}
finally
{
isDisposed = true;
}
}
Related
I have a WCF service hosted in IIS:
[WebServiceLogging]
public class ComplaintService : IComplaintService
This service has the WebServiceLogging attribute that does straightforward request/response logging into the database:
public class WebServiceLoggingAttribute : Attribute, IServiceBehavior {
SomeDatabaseConnection connection; // unmanaged resource
... interface implementations
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) {
IDispatchMessageInspector messageInspector = new WebServiceLogger(connection, _operations);
foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher endpointDispatcher in dispatcher.Endpoints)
{
DispatchRuntime dispatchRuntime = endpointDispatcher.DispatchRuntime;
dispatchRuntime.MessageInspectors.Add(messageInspector); // pass the logger into WCF.
}
}
}
}
Logging work is done from the WebServiceLogger, which uses the SomeDatabaseConnection unmanaged resource:
public class WebServiceLogger : IDispatchMessageInspector {
public object AfterReceiveRequest {
... gather Request data.
}
public void BeforeSendReply {
... gather Request data.
... Log using ADO.NET
... Dispose of Command object. No Connection closing!
}
}
I need to close the connection within WebServiceLogger once I'm done with logging. Options I've identified are:
Implement an IDisposable on WebServiceLogging class and do a Dispose() there or
Dispose of SomeDatabaseConnection directly from WebServiceLogger.BeforeSendReply()
My questions here are:
IDispatchMessageInspectors (such as WebServiceLogger) passed into dispatchRuntime.MessageInspectors - I've noticed that this object is not recreated per each request, but rather only once on the first request towards my service. How are such objects disposed of? Does WCF call `Dispose()˙ on them or should I use some other approach here?
Since we're at it, I have a nagging thought that perhaps using unmanaged resources in an Attribute is not such a good idea. Googling for c# attribute dispose didn't yield any results (there is one result on destructor, though). Any critiques on this approach?
Open and close a connection inside the BeforeSendReply method; i.e. make it a local variable (with a using-block, etc.).
Something like this:
public void BeforeSendReply {
... gather Request data.
using (var conn = new SqlConnection(...)) {
... Log using ADO.NET
}
}
The overhead is usually irrelevant (as ADO.NET uses connection pooling and won't really open/close a brand new connection). Second, and most importantly, that way you don't have to think about how your interceptor instance is used/called in a multithreaded (parallel requests) scenario.
That also matches better the unit of work pattern, that would be typically used if you did the same thing in the implementation method of an OperationContract. If you think about it, the interceptor points (AfterReceiveRequest and BeforeSendReply) are really just extensions of such method implementations (kind of AOP).
I am developing an Asp.net MVC application, and I have created an error handling system that forces me to create the following code per function in my BLL.
try
{
...
_unitOfWork.Save(nameof(Function));
}
catch
{
if (rollbackTo != null)
{
_unitOfWork.RollbackToSave(rollbackTo);
}
else
{
_unitOfWork.Rollback();
}
throw;
}
this basically allows me to manage my transactions per request, and manage the transaction's error handling without my Controllers knowing about the actual way that this is being done - it only allows it to decide whether or not the transaction will continue (rollbackTo parameter)
What I am wondering is, is there a way for me not to have to write this piece of code over and over? I thought about just throwing an exception, and then handle it in my pipeline - but since I need to return a valueable response to the user, and not just a 500 code - this isn't really an option. I thought about maybe creating a base class that calls and abstract method - and implementing it per function - but that won't work either, since the parameters can change. Any Ideas?
Yes, this is fairly standard.
For example, in the base class
public void DoSomethingAndRollbackThenThrow(Action<IUnitOfWork> action)
{
try
{
...
action(_unitOfWork);
}
catch
{
if (rollbackTo != null)
{
_unitOfWork.RollbackToSave(rollbackTo);
}
else
{
_unitOfWork.Rollback();
}
throw;
}
}
And then you can call it from derived class like so
public void DoSomethingSpecific()
{
base.DoSomethingAndRollbackThenThrow(unitOfWork => {
_unitOfWork.Save(nameof(Function));
});
}
You can use an AOP(Aspect Oriented Programming) framework.
You can "weave" some functionalities to your methods with just implementing for one time and adding some attributes.
More about AOP:
https://en.wikipedia.org/wiki/Aspect-oriented_programming
An easy-to-use open source AOP Framework:
https://github.com/AntyaDev/KingAOP
There are also a bunch of alternatives (both commercial and open source). Google may give you good results about alternatives.
What is the best practise for Disposing/Cleaning up a web service proxy instance after synchronous usage?
How does the answer differ if the proxy class is derived from SoapHttpClientProtocol versus ClientBase<T>?
Background
I'm trying to figure out why one of my WCF web services sometimes seems to get into a state where it no longer reponds to service calls. Basically it seems like it hangs and for now I don't really have any hard data to figure out what's going on when this occurrs.
One thing that I suspect might be an issue is the fact that this WCF service is itself doing web service calls to a few other services. These other services are called (synchronously) using proxies that are derived from SoapHttpClientProtocol (made using wsdl.exe) and at this time these proxy instances are left to be cleaned up by the finalizer:
...
var testProxy = new TestServiceProxy();
var repsonse = testProxy.CallTest("foo");
// process the reponse
...
So should I simply wrap these up in a using(...) { ... } block?
...
using(var testProxy = new TestServiceProxy())
{
var repsonse = testProxy.CallTest("foo");
// process the reponse
}
...
What if I were to change these proxy classes to be based on ClientBase<T> by recreating them using svcutil.exe? Based on my research so far, it seems the Dipose() method of classes derived from ClientBase<T> will internally call the Close() method of the class and this method might in turn throw exceptions. So wrapping a proxy based on ClientBase<T> in a Using() is not always safe.
So to reiterate the question(s):
How should I clean up my web service proxy after using it when the proxy is based on SoapHttpClientProtocol?
How should I clean up my web service proxy after using it when the proxy is based on ClientBase<T>?
Based on my best efforts to find the answer to this question, I'd say that for SoapHttpClientProtocol based proxies (regular .asmx web service proxies) the correct way is to simly wrap it in using():
using(var testProxy = new TestAsmxServiceProxy())
{
var response = testProxy.CallTest("foo");
// process the reponse
}
For proxies based on ClientBase<T> (WCF proxies) the answer is that it should not be wrapped in a using() statement. Instead the following pattern should be used (msdn reference):
var client = new TestWcfServiceProxy();
try
{
var response = client.CallTest("foo");
client.Close();
// process the response
}
catch (CommunicationException e)
{
...
client.Abort();
}
catch (TimeoutException e)
{
...
client.Abort();
}
catch (Exception e)
{
...
client.Abort();
throw;
}
I'm writing a program using the Managed WiFi API. Here's how I get all the networks in range:
void UpdateNetworks()
{
networks = new List<Wlan.WlanAvailableNetwork>();
WlanClient client = new WlanClient();
foreach(WlanClient.WlanInterface iface in client.Interfaces)
{
Wlan.WlanAvailableNetwork[] nets = iface.GetAvailableNetworkList(0);
foreach(Wlan.WlanAvailableNetwork net in nets)
networks.Add(net);
}
}
The problem is that after 18 calls to this method I can no longer connect:
(0x80004005): An attempt was made to
establish a session to a network
server, but there are already too many
sessions established to that server.
Here's the constructor that's throwing the exception:
public WlanClient()
{
Wlan.ThrowIfError(
Wlan.WlanOpenHandle(Wlan.WLAN_CLIENT_VERSION_XP_SP2, IntPtr.Zero, out negotiatedVersion, out clientHandle));
try
{
Wlan.WlanNotificationSource prevSrc;
wlanNotificationCallback = new Wlan.WlanNotificationCallbackDelegate(OnWlanNotification);
Wlan.ThrowIfError(
Wlan.WlanRegisterNotification(clientHandle, Wlan.WlanNotificationSource.All, false, wlanNotificationCallback, IntPtr.Zero, IntPtr.Zero, out prevSrc));
}
catch
{
Wlan.WlanCloseHandle(clientHandle, IntPtr.Zero);
throw;
}
}
I believe this is because the client never closes the connections it opens. How do I close them explicitly? There's handle closing in the catch block, but it requires access to the client's private parts.
I have the same problem.
I tried Mr Joe White solution but I received an error that wlanClient cannot be converted to System.IDisposable.
Since this problem is related to disposal of WlanClient instances, I only defined 1 instance as class member and used it so many times in method [void UpdateNetworks()]. I did not receive any error.
Remove line
WlanClient client = new WlanClient();
from your method and define it in your class. like the following:
public partial class frm_main : Form
{
private WlanClient client = new WlanClient();
private void UpdateNetworks()
{
var networks = new List<Wlan.WlanAvailableNetwork>();
foreach (WlanClient.WlanInterface iface in client.Interfaces)
{
Wlan.WlanAvailableNetwork[] nets = iface.GetAvailableNetworkList(0);
foreach (Wlan.WlanAvailableNetwork net in nets)
networks.Add(net);
}
MessageBox.Show(networks.Count.ToString());
}
}
Reference: Managed WiFi error
Since you're seeing problems only after a certain number of iterations, the problem is likely resource exhaustion of some sort, which sounds like resources aren't getting cleaned up in a timely manner.
From the comments above, it sounds like you're not disposing your WlanClient instances, which may be part (or all) of the problem. I can understand why you're not disposing them, though, because they don't give you any obvious way to do so. This seems like a really problematic design on their part. There are all kinds of design guidelines that say a class like this should give you either a public Dispose method or a public Close method, but even though they have both those methods, they deliberately made them both private.
But the class does implement IDisposable, so you can still clean it up by adding a using block:
using (var wlanClient = new WlanClient()) {
....
} // wlanClient will be disposed when flow leaves the block
This will make sure all of the object's resources get cleaned up at the moment flow leaves the using block (even if flow is leaving because there was an exception). Your connections will be closed, your unmanaged memory released, and whatever else needs to happen.
I'd like to override the Dispose method of generated proxy (ClientBase) because of the fact that disposing of a proxy calls Close and can throw an exception when the channel is faulted.
The only way I came up was to create a partial class to my generated proxy, make it inherit from IDisposable:
public partial class MyServiceProxy : IDisposable
{
#region IDisposable Members
public void Dispose()
{
if (State != System.ServiceModel.CommunicationState.Faulted)
Close();
else
Abort();
}
#endregion
}
I did some test and my Dispose method is indeed called.
Do you see any issue with this strategy?
Also, I don't like the fact that I'll have to create this partial class for every generated proxy.
It be nice if I was able to make my proxy inherit from a base class...
There's no issue with it. Customizing designer-generated code in this fashion is exactly the feature that partial classes are intended to provide, and this is one of the recommended ways of dealing with the broken IDisposable implementation on ClientBase.
As for having to re-implement this code for every WCF client - unfortunately, yes, you will, if you want to use the IDisposable pattern with these. You could extract the if/else block into a utility method but you would still have to create a partial class for each one and override Dispose.
Seeing as how the above is rather tedious to do, many people choose to use the Service Proxy Helper instead, since it doesn't require writing any new code.
I use a slightly modified version, myself:
public static class Service<TProxy>
where TProxy : ICommunicationObject, IDisposable, new()
{
public static void Using(Action<TProxy> action)
{
TProxy proxy = new TProxy();
bool success = false;
try
{
action(proxy);
proxy.Close();
success = true;
}
finally
{
if (!success)
{
proxy.Abort();
}
}
}
}
Which allows writing this kind of code:
Service<MyServiceClient>.Using(svc => svc.PerformOperation());
Or:
Service<MyServiceClient>.Using(svc =>
{
var result = svc.PerformOperation();
ProcessResult(result);
});
Note: WCF proxies are expensive to create, so you generally want to try to keep them alive as long as possible instead of creating and disposing them every few seconds (or more). This is intended for clients that are infrequently-used.
Overriding the Dispose() method is a perfectly valid strategy.
There are a few other options in the answers to this question: What is the best workaround for the WCF client `using` block issue?