We have been tearing our hair out around here because we can’t find a way in Silverlight 2.0 Beta to write a method that blocks the UI thread while it fetches data.
In case you are not aware of this problem, permit me to illustrate.
Suppose in the bowels of your business logic you have a validation rule that says: “total of order not to exceed the customer’s maximum cost for a single order”.
You’re using a domain model with objects that have dotted navigation. You write your rule along the lines of:
… TotalCost(myOrder.Details) < myOrder.Customer.SingleOrderLimit …
Unfortunately, both myOrder.Details and myOrder.Customer.SingleOrderLimit could involve lazy loads of the Details and the Customer.
The UI that enabled the user to create a new detail item for the order is not aware of this rule and didn’t pre-fetch Details and/or SingleOrderLimit.
No problem in regular .NET. You just wait while you lazy load the SingleOrderLimit from the database.
Big problem in Silverlight.
All server calls have to be asynchronous. Your fetch of the SingleOrderLimit is going to have to return immediately; the value will be accessible later during the asynch callback.
Ok, you try to rewrite SingleOrderLimit to stall the UI thread until you get the callback. But there’s no way to do it. If you sleep the thread, you never hear the callback. You make the server call on a worker thread and sleep the UI thread; you never hear the callback. Sit and spin on the UI thread? You never hear the callback. What’s with that?
I understand that I can write synchronous code on the background thread. The problem is that I can't make the UI thread wait for the result.
So you try to live within this crazy world. You decide that you will somehow detect this particular problem and you stash the validation object somewhere, postponing its execution until all the dependent server trips have completed; in my example, the validator can’t run until Details and Customer have been retrieved and how I knew to stack these dependencies is anyone's guess. Good thing they're mutually independent requests because if one query depended on the outcome of another query, the logic would get really twisted.
Meanwhile your original validation call - the one that got us into this mess - must return with some indication like “I don’t know”.
It can't report “everything is ok” or “it’s invalid”. So you have to be sure that the ancestor caller somewhere way up the stack postpones whatever it was doing (like trying to save the order) until you have a definitive answer. And, of course, when it becomes possible to render an answer, you have to remember to renew your originating operation (e.g., the save). You weren't just going to tell the user "Sorry, I can't save yet, not enough information ... try again soon" were you?
Let's say you got that all figured out. But watch out. Maybe your WPF-ish UI is binding to objects in your unit-of-work container. Over on your worker thread you're doing some synchronous magic that fetches Customer and Detail objects. You better not put them into that container on the UI thread ... because it's not thread-safe and if WPF is looking for 'em there's going to be trouble! You better be ready to fetch Customer and Detail into a separate container and then martial them back across the thread boundary in the callback. Oh joy.
You see where I’m going with this. Application programming just became immensely difficult. You can’t write a real program if every data fetch is async. Your UI controller shouldn't have to anticipate every bit of data you might possibly need upfront either. This is a disaster.
Do you know what to do about this? Do you know anyone who does? We’re beating every bush and so far, nada.