Apoorv Shrivastava
Apoorv Shrivastava

Reputation: 33

How do I detect waiting asynchronous wcf calls?

I make calls to a WCF service from my silverlight application. I am doing this asynchronously and I am not blocking execution after making the async. call (that means, I am not using wait-join mechanism frm this page). I do not want the flow to get blocked.

However, I would like to detect that the WCF call has gone into a wait state so that I can show a busy icon on the UI - a visual communication indicating that things are happening behind the UI.

I can change my code such that I can start to animate the busy icon and stop that animation when the asynchronous call completes.

However, this is a lot of bolierplate code, and with more calls being made throughout the client code, this is only going to get messier.

So, is there any method or property exposed by the wcf service client reference code that can be used to trigger off events when any async wcf service calls go into a wait state, and likewise, trigger off events when the all async wcf service calls finish?

Upvotes: 3

Views: 10834

Answers (1)

Peter McG
Peter McG

Reputation: 19035

There is no property or event on the generated client reference class that can be used to identify that an asynchronous call to a method of a Silverlight WCF service is currently in progress. You can record this yourself using a simple boolean variable though, or by using the blocking thread synchronization that you mentioned you want to avoid in this case.

Here's an example of how to do what you want using the Silverlight ProgressBar control to indicate waiting/working on a call to a very simple Silverlight web service:

Page.xaml:

<UserControl x:Class="SilverlightApplication1.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="100">

    <StackPanel x:Name="LayoutRoot" Background="White">
        <Button x:Name="ButtonDoWork" Content="Do Work"
                Click="ButtonDoWork_Click"
                Height="32" Width="100" Margin="0,20,0,0" />
        <ProgressBar x:Name="ProgressBarWorking"
                     Height="10" Width="200" Margin="0,20,0,0" />
    </StackPanel>
</UserControl>

Page.xaml.cs:

using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using SilverlightApplication1.ServiceReference1;

namespace SilverlightApplication1
{
    public partial class Page : UserControl
    {
        public bool IsWorking
        {
            get { return ProgressBarWorking.IsIndeterminate; }
            set { ProgressBarWorking.IsIndeterminate = value; }
        }

        public Page()
        {
            InitializeComponent();
        }

        private void ButtonDoWork_Click(object sender, RoutedEventArgs e)
        {
            Service1Client client = new Service1Client();
            client.DoWorkCompleted += OnClientDoWorkCompleted;
            client.DoWorkAsync();

            this.IsWorking = true;
        }

        private void OnClientDoWorkCompleted(object sender, AsyncCompletedEventArgs e)
        {
            this.IsWorking = false;
        }
    }
}

Setting IsIndeterminate to true after the asynchronous call to DoWork makes the progress bar animate indeterminately like this:

alt text http://www.freeimagehosting.net/uploads/89620987f0.png

Because the callback to OnClientDoWorkCompleted happens on the UI thread it's fine to change the value of the IsIndeterminate property back to false in the method body; this results in a non-animating blank ProgressBar again as the working/waiting is now finished.

Below is the code for the web service and the DoWork method that the above code calls asynchronously, all it does it simulate some long running task by sleeping for 5 seconds:

using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Threading;

namespace SilverlightApplication1.Web
{
    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class Service1
    {
        [OperationContract]
        public void DoWork()
        {
            Thread.Sleep(TimeSpan.FromSeconds(5.0));
            return;
        }
    }
}

Upvotes: 4

Related Questions