Emulating Synchronous Web Service Call in Silverlight 3
As we know, only option for web service calling in Silverlight is asynchronous and Silverlight framework does not provide any API for synchronous call. In this post, i will show how we can emulate synchronous web service call using the default asynchronous web service call mechanism of Silverlight.
One simple idea to solve this problem is sleeping UI thread after web service call until result back. But it will block UI thread. So Dispatcher will be blocked and UI will be freeze. No interaction will be possible with the Silverlight UI. So blocking the UI thread is not the Solution.
To solve this problem, i have performed asynchronous service calling in a worker thread and blocked the worker thread until result is retrieved. Result is send to the UI thread using Dispatcher.invoke to Update UI. To block the worker thread until the result is retrieved from the web service, I have used thread synchronization mechanism AutoResetEvent. For emulating synchronous web service call, the following code has been used.
1: public partial class MainPage : UserControl
2: {
3: private AutoResetEvent autoResetEvent = new AutoResetEvent(false);
4: public MainPage()
5: {
6: InitializeComponent();
7: StartServerTimeUpdatingSyncronosly();
8: }
9: private void StartServerTimeUpdatingSyncronosly()
10: {
11: try
12: {
13: Thread thread = new Thread(new ThreadStart(UpdateTimeSyncronosly));
14: thread.Start();
15: }
16: catch (Exception ex)
17: {
18: MessageBox.Show(ex.Message, "SynchronousWebServiceCalling", MessageBoxButton.OK);
19: }
20: }
21: private void UpdateTimeSyncronosly()
22: {
23: SynchronousWebServiceCalling.ContentServiceReference.ContentServiceClient contentServiceClient = new SynchronousWebServiceCalling.ContentServiceReference.ContentServiceClient();
24: contentServiceClient.ReturnServerTimeCompleted += new EventHandler<SynchronousWebServiceCalling.ContentServiceReference.ReturnServerTimeCompletedEventArgs>(ReturnServerTimeCompleted);
25: string message = "Retrieving new server time...";
26: while (true)
27: {
28: this.Dispatcher.BeginInvoke(new Action<string>(DisplayBusyMessage), message);
29: contentServiceClient.ReturnServerTimeAsync();
30: autoResetEvent.WaitOne();
31: }
32: }
33: void ReturnServerTimeCompleted(object sender, SynchronousWebServiceCalling.ContentServiceReference.ReturnServerTimeCompletedEventArgs e)
34: {
35: this.Dispatcher.BeginInvoke(new Action<string>(DisplayTime), e.Result);
36: string message = "New server time is retrieved";
37: this.Dispatcher.BeginInvoke(new Action<string>(DisplayBusyMessage), message);
38: System.Threading.Thread.Sleep(5000);
39: autoResetEvent.Set();
40: }
41: private void DisplayTime(string time)
42: {
43: tblTime.Text = time;
44: }
45: private void DisplayBusyMessage(string message)
46: {
47: StatusLabel.Text = message;
48: }
49: }
Here AutoResetEvent plays an important role to implement this. It has a method WaitOne. According to MSDN, WaitOne blocks the current thread until the current instance receives a signal. So in the worker thread, we call WaitOne() after calling the web service method to block the worker thread until the result of web service operation is received. When the result of web service operation is received in ReturnServerTimeCompleted method, Set() method of AutoResetEvent is used to signal the worker thread so that next consecutive web service call can be made.
You can download the sample code from here. Hope this will save some of your time.