Sunday, February 1, 2015

WCF Asynchronous Service Methods and Timeouts Gotcha

Asynchronous Methods in WCF

I have tested WCF asynchronous service methods on several occasions and I have come to a few conclusions. These of course are just my opinions and I am open to conversation about it. On to my conclusions:
  1. On the server side - you can declare a method as being asynchronous in the method's operation contract as an attribute - but I fail to see how it is at all useful when you can just generate all of the asynchronous methods yourself on the client side. If you are using task based operations on the client side - all of your hard work for making your method asynchronous is completely ignored and thus is made pointless.
  2. On the client side - you have a choice between generated asynchronous based operations and generated task based operations. If you are using Framework 4.5 or have the opportunity to just upgrade to Framework 4.5 - do so and use Tasks. The older methodology of asynchronous based operations is just painful to work with and feels obsolete in comparison to Tasks (TPL).
  3. This is my final point, but my most important point and motivator for this article. If you are trying to solve a problem with Timeouts because you have a long running task that you want to kick off via WCF - then using Asynchronous methods WILL NOT HELP YOU AT ALL.

Elaboration of Point 3 - Service Timeout Gotcha!

Using Asynchronous methods in your WCF service WILL NOT help you avoid a timeout from occurring! If you have a long running task in your WCF Service on the Server Side and you are trying to kick off this long running task from the Client Side - if your long running task runs longer than your allotted timeout settings for your WCF binding configurations - you will see an error like this one and there is nothing you can really do about it except increase your time out (which is not a good long term solution!):
This request operation sent to net.tcp://localhost/WcfService.svc did not receive a reply within the configured timeout (00:00:10).  The time allotted to this operation may have been a portion of a longer timeout.  This may be because the service is still processing the operation or because the service was unable to send a reply message.  Please consider increasing the operation timeout (by casting the channel/proxy to IContextChannel and setting the OperationTimeout property) and ensure that the service is able to connect to the client.
Please note that it indeed says 10 seconds in the above error message - as I was testing the limits of the timeout and I would rather wait seconds rather than minutes while testing the timeouts. In other words this is not a realistic timeout value and is meant for testing only. However - this still doesn't change the fact that the timeout occurred while I was running a 20 second long running process.

Conclusion

Like I said above - I don't really see the usefulness in using Asynchronous methods in WCF if it isn't going to alleviate the one problem we all ultimately end up running into - which is a WCF Service Method may take too long to complete and our program breaks while we wait for it to complete. The service Timeout is absolute.

Therefore this means using a different approach such as:
  • If possible taking large requests and chunking them into smaller requests. Example: processing 1000 objects in one request vs. process 100 objects in 10 requests.
  • Using a method as a one way call, setting and forgetting about it: https://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontractattribute.isoneway(v=vs.110).aspx
  • Making your WCF Service Method call you back via a different service pipeline. This approach could get messy, but let's say your client calls the server, when the server is finished with the request it can call the client back using a service exposed by the client.
  • Putting in a request that immediately returns a tracking ID, then using a different method to check the progress of your request using that tracking ID. In this approach think about buying something from an online retailer. You put in the request and you can track your shipment using a tracking number. The only difference here is instead of the package being delivered to your doorstep you have to go pick it up when it is declared "finished".

Resources

These are all resources I used to conduct my research and testing. There is plenty of information on how to implement asynchronous methods in WCF - just not enough information on how to handle long running tasks in a WCF service.

No comments:

Post a Comment