One of the things you’ll notice when you start writing Silverlight applications is that you cannot call a service synchronously anymore, as you could in, for example, a typical ASP .NET WebApp. In Silverlight, everything is async by default – which means you won’t have a GUI that hangs, for example. Great, right? That’s what I thought as well.
But: you’ll have to change the way you used to think about your programming model. If you don’t, and if you keep thinking about it as you did before, you’ll run into quite a few possible problems.
A little example: a certain project I’ve been working on consists of generating a Silverlight GUI based on an XML, which will typically result in some kind of questionairre, with lots of panels (which represent a step in the questionairre), dropdowns, checkboxes to tick and untick, fields to fill out, et cetera. Some of these checkboxes and fields require some kind of validation or rule: if you check one checkbox, other checkboxes must be enabled/disabled, or certain text fields must be filled out. So we wrote some rules. Some of the text fields that must be filled out must have values that are of a certain type, or are in a certain range – so we wrote some validators. Other textfields must have a value that corresponds to a database value, before you can continue to the next step. So we … got stuck!
Problem: we used to validate our fields when clicking the "next"-button to go to the next step. Worked flawlessly, untill we ran into the database validators: these call services which check a field value against a value in the database. Easy way out: call the service synchronously, and only continue with the other checks once you get a returnvalue. But Silverlight doesn’t allow a service to be called synchronously… and when calling the service async, there’s no easy way of "blocking" the program flow ’till we get something back from our service call. Or is there?
Well… there are certain techniques some people try to apply to get their async service to behave as if it were sync, like toying with some threading options, using ManualResetEvents, or other "smart" tricks.
One simple word of advice: don’t.
None of them really work, and they all come down to one thing: your application architecture/model is wrong. Or better: it’s not in touch with the way modern applications are designed – or should be designed.
Don’t get me wrong – I’ve been programming synchronously for years, as have most people, so I do understand the challenges you’ll face when this isn’t an option anymore. But don’t try to get an async service to behave sync – you will fail, and if you don’t, you’ll end up with bulk, unnecessary code. Change the way you think, change your architecture, so it fits the async programming model. This is ALWAYS possible. It will require some effort, but you will succeed, and in return, you’ll get an application that not only works as the language you program in has intended, but at the same time is ready for the future, AND stays responsive. Better yet: think AHEAD.
To get back to my little validation problem: instead of trying to incorporate some kind of "waiting"-behaviour for my validation, we turned the model around. A value isn’t valid by default anymore, it’s invalid by default; my database validation services can now run async, and the value will become valid (if it is) when the async call returns. Only when everything is valid, the user is able to continue with the next step. And because a value is invalid by default, the user can never continue to the next step untill all async database validation service calls are completed. One little (well…) change, a world of difference.
To end this post with a really stupid one-liner: the future is async, get used to it. 😉