生成的客户端引用类上没有可用于标识对 Silverlight WCF 服务方法的异步调用当前正在进行的属性或事件。不过,您可以使用简单的布尔变量自己记录这一点,或者使用您提到的在这种情况下要避免的阻塞线程同步。
下面是一个示例,说明如何使用Silverlight ProgressBar control 指示正在等待/处理对一个非常简单的 Silverlight Web 服务的调用:
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;
}
}
}
在异步调用 DoWork 后将 IsIndeterminate 设置为 true 会使进度条像这样不确定地动画:
alt text http://www.freeimagehosting.net/uploads/89620987f0.png
因为对 OnClientDoWorkCompleted 的回调发生在 UI 线程上,所以可以在方法主体中将 IsIndeterminate 属性的值改回 false;随着工作/等待现在完成,这将再次导致非动画空白 ProgressBar。
下面是Web服务的代码和上面代码异步调用的DoWork方法,它所做的只是通过休眠5秒来模拟一些长时间运行的任务:
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;
}
}
}