Synchronous & Asynchronous Operations on Silverlight
A few days ago I wrote a very simple Silverlight application. Unfortunately I ended up with an infinitely locked UI thread.
Basically, the application was supposed to fetch configuration data from my server and use it. I added a reference to my server side service, and of course, Visual Studio generated an asynchronous proxy for me.
For a reason that is irrelevant for this post, I decided to wrap the asynchronous server call with a synchronous helper class. My helper class exposed a synchronous method which his parameters are the same as the server method except for the callback parameter that is not needed.
“One code of block worth a thousand words”, that’s the saying, right? :)
Let’s have a look at my helper class:
class SynchronousConfigReader
{
private AutoResetEvent m_callbackCompleted;
private string m_configValue;
public SynchronousConfigReader()
{
m_callbackCompleted = new AutoResetEvent(false);
}
public string GetConfigData(string configKey)
{
ConfigServiceProxy proxy = new ConfigServiceProxy();
proxy.GetConfigData(configKey, GetConfigData_Completed);
m_callbackCompleted.WaitOne();
return m_configValue;
}
private void GetConfigData_Completed(object sender, GetConfigDataEventArgs e)
{
m_configValue = e.ConfigValue;
m_callbackCompleted.Set();
}
}
As you can see, my helper’s “GetConfigData” method simply calls the asynchronous proxy method, providing a callback of the helper itself. Then, it waits for an AutoResetEvent which is being set in the callback method.
As I said at the beginning of this post, calling my helper’s “GetConfigData” locked my UI thread forever. So, I found myself digging in my code over and over again, searching for a clue for this strange behavior. I also made sure that there is nothing wrong with my service, and this is when I found the first clue – My service didn’t receive a single call!
I can write many pages, describing the ways I debugged this behavior, but it doesn’t really matter, and honestly, it is not very interesting as well.
So, After debugging, googling, debugging again, and googling again I found the cause for this behavior.
Apparently, Silverlight applications does not execute asynchronous web requests immediately. instead, the requests are being queued until the UI thread is not “busy” executing your code. Why? because the UI thread is the only thread that executes asynchronous web requests in a Silverlight application.
Think you can fool it? I thought I can. I modified “GetConfigdata” so that it uses a Thread Pool thread in order to execute the proxy’s asynchronous method. This didn’t work as well. I can’t say for sure since I wasn’t able to find an MSDN page or any other Microsoft official documentation that approves my assumption, but it seems that all asynchronous web requests must be executed by the UI thread, regardless of the thread that originally initiated them.
If you really want to, you can search for workaround and you will find some, eventually. I dropped the idea, thinking that such behavior cannot be a bug, it was intentionally implemented, and probably with a good reason (which honestly, I haven’t figured out yet).
Anyway, here are my conclusions:
- Obviously, you cannot/shouldn’t try to turn asynchronous server calls to synchronous calls in Silverlight.
- You should never block the UI thread on a Silverlight application. It seems that it has more responsibilities than just drawing UI controls.