I would like to know what is a proper way to handle timeouts in a WCF service.
I have a service that uses sessions. The client does a Connect, various calls (as the user interacts with the client app) and then, at some point, does a Disconnect. The Disconnect operation performs a clean-up on the server (such as releasing COM objects). However, the client can (abnormally) terminate (for various reasons) without calling Disconnect. After the receiveTimeout expires, the services is aborted. I need to handle this in a way that allows me to proper clean-up the session. How can I do that?
Is there an event I can handle? An interface that I can implement and customize the service with it? I have looked, but did not find something. IErrorHandler does not help with the timeouts.
I have thought of a timer on the service that is reset every time a call is made to the service. When the timer elapses, the client is considered disconnected and the service can clean-up the session. Is this appropriate? (This interval should be always smaller than the receiveTimeout of the binding.)
As per http://msdn.microsoft.com/en-us/library/ff183865.aspx, WCF sessions timeout by default after 10 minutes or whatever the receiveTimeout specifies. If your service class implements IDisposable, I believe the Dispose() call should come in at this time, which would give you a second/last chance to clean up any outstanding resources.
Related
In my client/server applications, I want a single duplex WCF channel to be available for communication with its server - sort of a background connection that isn't strictly necessary for the client application to run, but is desirable for reporting status to the server. I have a Ping() call and Echo() callback in the IServerContract and IClientContract respectively.
I implement class ServerProxy : System.ServiceModel.DuplexClientBase<IServerContract> with the pass-thru methods to base.InnerChannel.
If I create var proxy = new ServerProxy(...) in my client, I can just begin calling proxy.Ping() and WCF will automatically open the connection for the first call and perform the operation call immediately after. However, the first call always takes ~10 seconds because of channel initialization and authentication. (I'm using windows authentication, Message-based security, EncryptAndSign.) Subsequent calls are quicker.
I believe this 10 seconds is unavoidable, but there is usually time prior to the first call by the client to the server during which this initialization could happen. So rather than wait for the auto-open feature of DuplexClientBase, I open the channel early with a call to proxy.InnerDuplexChannel.Open(). (proxy.Open() throws an exception and this indirection seems to avoid it.)
Unfortunately, authenticating the client-to-server channel does not also authenticate the server-to-client callback channel. Instead, the first call by the server to the client ALSO requires ~10 seconds. Since I'm using netTcp binding I'm surprised by this, but I'll assume it is to be expected for now.
How can I open the callback channel preemptively as well?
I could require the client to call some Login() method instead, but I don't believe that WCF should strictly require an operation before user-code can be aware of a connected client!
Hint(?): I imagine that this code would have to go in a place in the WCF pipeline/lifecycle where the server has the opportunity to perform custom actions upon a client-connected event (and BEFORE any operation message is transmitted). This integration point has so far eluded me.
In my current web project, we perform a ClientFactory.CreateChannel for every method call to a remote service.
Is this really necessary?
What is the best practice?
This depends to some extent what your requirements are. Opening a channel is expensive, relatively speaking. Best practice is to have the class that is doing the remote calls implement IDisposable, it should make a call to ClientFactory.CreateChannel once, use the channels in all the method calls, and close the channel when the Dispose method is called. That said, if the time between the calls to methods that call to a remote service is long (longer then the default idle timeout on the channel which is 10 minutes) then doing a ClientFactory.CreateChannel isn't particularly harmful, but I would say it would still be better to go the IDisposable route and encapsulate use of the class with the 'using' keyword
creating a new channel for each method call comes in bad practice "generally".
For Duplex WCF Service
creating a single channel and using it until there is no need to communicate with server anymore/ or that channel gets closed.
After creating the channel, before making any call to server, its recommended to check channel's state (Error, opening, closed).
Registering the channel closed/Error events is recommended to get to know immmediatley when it occurs. so you can take necessary actions or/and create the channel again with same object channel object reference.
For Normal WCF service
Create the proxy pattern, to create channel/ to re-use/ re create, error handling and disposing. set the appropiate inactivity timeout along with WCF client's proxy appropiate configuration which suits best with your solution.
Always Load test!!!!
I have a service that uses callback operations to call back its client. Is there a away to notify the client when Service goes down? An exception is raised when client goes down during callback, but with service goes down the subscription is lost but client is not notified.
Does WCF support some heartbeat operation to check the state of the service?
Thanks
No, there's no such thing as a "check if this service call will succeed" method.
You need to call the service and be prepared to handle any exceptions that occur during the service call.
There's really no reliable or useful way to check for service availability. All that a heartbeat could check for is that you can call your service method right now - but a fraction of a second later, that connection might be gone (cable has been unplugged or severed, server has crashed - the possibilities of things going wrong are endless......), too. It cannot check if all the necessary background services and databases etc. are available.
So in reality, such a heartbeat check is quite pointless. Just call the service, hope for the best, and be prepared for the worst! Wrap your service calls in good exception handling, and get on with it.
In my client program, there is a WCF connection that is opened at startup and supposedly stays connected til shutdown. However, there is a chance that the server closes due to unforeseeable circumstances (imagine someone pulling the cable).
Since the client uses a lot of contract methods in a lot of places, I don't want to add a try/catch on every method call.
I've got 2 ideas for handling this issue:
Create a method that takes a delegate and executes the delegate inside a try/catch and returns an Exception in case of a known exception, or null else. The caller has to deal with nun-null results.
Listen to the Faulted event of the underlying CommunicationObject. But I don't see how I could handle the event except for displaying some error message and shutting down.
Are there some best practices for faulted WCF connection that exist for app lifetime?
If you do have both ends of the wire under your control - both the server and the client are .NET apps - you could think about this approach instead:
put all your service and data contracts into a shared assembly, that both the server and the client will use
create the ChannelFactory<IYourService> at startup time and cache it; since it needs to have access to the service contract, this only works if you can share the actual service contract between server and client. This operation is the expensive part of building the WCF client
ChannelFactory<IYourService> factory = new ChannelFactory<IYourService>();
create the actual communications channel between client and server each time you make a call, based on the ChannelFactory. This is pretty cheap and doesn't cost much time - and you can totally skip any thoughts about having to detect or deal with faulted channels.....
IYourService client = factory.CreateChannel();
client.CallYourServiceMethod();
Otherwise, what you basically need to do is wrap all service calls into a method, which will first check for a channel's faulted state, and if the client proxy is faulted, aborts the current one and re-creates a new one.
I wrote a blog post on exceptions in WCF that deals with how to handle this: http://jamescbender.com/bendersblog/Default.aspx
I have a Windows service that logs speed readings from a radar gun to a database. In addition, I made the service a WCF server. I have a Forms and a CF client that subscribe to the service and get called back whenever there is a reading that satisfies certain criteria.
This works in principle, but after some time the channel times out. It seems that there are some fundamental issues with long-running connections (see
http://blogs.msdn.com/drnick/archive/2007/11/05/custom-transport-retry-logic.aspx) and a duplex HTTP callback may not be the right solution. Are there any other ways I can realize a publish/subscribe pattern with WCF?
Edit: Even with a 2 hour timeout the channel is eventually compromised. I get this error:
The operation 'SignalSpeedData' could not be completed because the sessionful channel timed out waiting to receive a message. To increase the timeout, either set the receiveTimeout property on the binding in your configuration file, or set the ReceiveTimeout property on the Binding directly.
This happened 15 minutes after the last successful call. I am wondering if instead of keeping the session open, it is possible to re-establish a fresh session for every call.
Reliable messaging will take care of your needs. The channel reestablishes itself if there is a problem. WSDualHTTPBinding provides this for the http binding, and there is also a tcp binding that allows this. If you are on the same computer, named pipe binding will provide this by default.