Tuesday, February 17, 2009

Adventures while building a Silverlight Enterprise application part #7

Today I wanted to state this, although for some of you it may seem obvious, others may get caught up in this pitfall. Always make sure that any webservice you use from Silverlight is thread safe, even in the same session.

Here is what could happen. You have some UI action, for example the click of a button, which triggers a call to your webservice. Inside your webservice you use some non thread safe object, to do some operation, for example a SqlConnection to read some data from your database. All is well, but as you build your webservice you may consider to share this SqlConnection, because you need to do two queries within one call.

That's where things start going wrong. On first sight, everything seems to work fine. Until that is, you start bashing away on that button and all of a sudden your Silverlight application crashes mysteriously in the completed event of your service call.
After some debugging you may find out that this is caused by the fact that your SqlConnection failed for some reason. Some more debugging may tell you that the SqlConnection is actually closed, or in the state of being opened, or it may just throw an exception, telling you to remove your results and try again. Any of these is caused by the fact that you use a single SqlConnection to do more than one operation on.

"But what about performance?" I hear you ask. Well, what about it? There is never, and I mean never, a reason to reuse an instance of SqlConnection. The reason is that Microsoft provided us with a great feature called a connection pool, which will just cycle trough a set of already created connections for each request it gets. All you have to do is make sure you open the connection as late as possible and close it as soon as possible. This way you never hold on to a connection to long and the change of a connection pool running out of connections is as small as possible.

But what if you are using some other non thread safe object, that would impact performance when you re instantiate it for every call? One thing I would probably want to do is, disable the control that triggers the action, as soon as an action takes place and only enable it again as the action is complete, or maybe even at a later time, if that's appropriate. This way you make sure that a single user can not run multiple operations and performance should improve already.

Another solution may be to actually rethink the design of your service. Maybe you need a more extensive model than a standard service. For example, you could choose to build an actual Windows Service with a WCF interface. This would allow you to queue up any calls comming in and having them handled by other threads. This model would be useful to provide, for example, a search service.

Hope this was helpful to at least some of you and I'm looking forward to reading your comments.

No comments:

Post a Comment