彩票走势图

如何实现Silverlight同步(Synchronous)调用WCF服务

转帖|其它|编辑:郝浩|2011-01-10 17:25:22.000|阅读 1661 次

概述:在某些情况下我们的调用是需要同步进行,虽然Silverlight没有内置同步线程模式调用远端服务接口,但是我们可以通过多线程的处理来伪装出同步调用的实现。在.NET Framework的多线程编程中提供了丰富的线程接口,其中AutoResetEvent和ManualResetEvent在多线程编码中最为常用,本文将介绍如何通过AutoResetEvent的线程等待特性实现Silverlight同步调用远端WCF服务。

# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>

  Silverlight的RIA应用中访问远端的WebService或WCF服务,都是通过异步线程模式调用的。在某些情况下我们的调用是需要同步进行,虽然Silverlight没有内置同步线程模式调用远端服务接口,但是我们可以通过多线程的处理来伪装出同步调用的实现。在.NET Framework的多线程编程中提供了丰富的线程接口,其中AutoResetEvent和ManualResetEvent在多线程编码中最为常用,本文将介绍如何通过AutoResetEvent的线程等待特性实现Silverlight同步调用远端WCF服务。

一、定义WCF服务

  为了演示同步调用WCF服务的实现,提供一个简单的WCF服务接口,完成返回一本图书基本信息,WCF服务接口定义如下

[ServiceContract]
public interface IDataService
{
     [OperationContract]
     Book GetBook();
}

public class Book
{
     public int ID { get; set; }
     public string Name { get; set; }
     public string Author { get; set; }
     public double Price { get; set; }
}

接口提供一个返回图书基本信息的方法,包括图书编好,图书名,图书作者以及图书价格。接口具体的实现如下代码:

public class DataService : IDataService
{
     public Book GetBook()
     {
         return new Book
         {
             ID = 1001,
             Name = "《三国演义》",
             Author = "罗贯中",
             Price = 89.50
         };
     }
}

如上提供可正常运行的WCF服务接口,在需要调用接口的地方通过WEB引用既可生成该服务的客户端代理对象。

二、基于MVVM模式的视图模型

  MVVM模式的核心为INotifyPropertyChanged接口,对于实体模型对象和UI控件元素间提供了完善的同步更新特性。为了方便界面元素同步更新,这里引入了MVVP模式的简单应用。

public class ViewModelBase : INotifyPropertyChanged
{
     public event PropertyChangedEventHandler PropertyChanged;

     protected void RaisePropertyChangedEvent(string propertyName)
     {
         var handler = PropertyChanged;
         if (handler != null)
             handler(this, new PropertyChangedEventArgs(propertyName));
     }
}

还需要对应于服务接口中的Book对象定义一个ViewModel对象,详细如下代码所示:

public class BookViewModel : ViewModelBase
{
     private int iD;
     /// <summary>
     /// 图书ID
     /// </summary>
     public int ID
     {
         get { return iD; }
         set
         {
             iD = value;
             RaisePropertyChangedEvent("ID");
         }
     }

     private string name;
     /// <summary>
     /// 图书名称
     /// </summary>
     public string Name
     {
         get { return name; }
         set
         {
             name = value;
             RaisePropertyChangedEvent("Name");
         }
     }

     private string author;
     /// <summary>
     /// 图书作者
     /// </summary>
     public string Author
     {
         get { return author; }
         set
         {
             author = value;
             RaisePropertyChangedEvent("Author");
         }
     }

     private double price;
     /// <summary>
     /// 图书价格
     /// </summary>
     public double Price
     {
         get { return price; }
         set
         {
             price = value;
             RaisePropertyChangedEvent("Price");
         }
     }
}

三、基于AutoResetEvent的同步实现

  利用AutoResetEvent的线程等待特性,可以折中实现Silverlight同步调用远端WCF服务。其原理就是在Silverlight发起异步调用远端WCF的时候进行线程阻塞,比记录异步调用远端WCF服务接口的完成事件,当异步调用完成后就终止线程阻塞,从而获取状态事件对象中或得调用远程接口所返回的结果。由于视图模型对象实现了INotifyPropertyChanged接口能够及时的更新界面元素,以此间接的就实现了同步方式调用。

public class AsyncCallStatus<T>
{
     public AsyncCallStatus()
     {

     }

     public T CompletedEventArgs { get; set; }
}

public class BookFacade
{
     private AutoResetEvent autoResetEvent = new AutoResetEvent(false);

     public void GetBook(BookViewModel viewModel)
     {
         if (viewModel == null)
         {
             throw new ArgumentNullException("viewModel", "参数不能为空。");
         }

         DataService.DataServiceClient client = new DataService.DataServiceClient();
         client.GetBookCompleted += client_GetBookCompleted;

         var status = new AsyncCallStatus<GetBookCompletedEventArgs>();
         client.GetBookAsync(status);
         //阻塞线程
         autoResetEvent.WaitOne();

         if (status.CompletedEventArgs.Error != null)
         {
             throw status.CompletedEventArgs.Error;
         }
         var book = status.CompletedEventArgs.Result;
         viewModel.ID = book.ID;
         viewModel.Name = book.Name;
         viewModel.Author = book.Author;
         viewModel.Price = book.Price;
     }

     private void client_GetBookCompleted(object sender, GetBookCompletedEventArgs e)
     {
         var status = e.UserState as AsyncCallStatus<GetBookCompletedEventArgs>;

         status.CompletedEventArgs = e;
         //终止线程阻塞
         autoResetEvent.Set();
     }
}

四、Silverlight前端调用

  Siverlight前端就简单布局一个表单作为数据呈现界面,其代码如下:

<Grid x:Name="LayoutRoot" Background="White">
     <Grid HorizontalAlignment="Left" Name="grid1" VerticalAlignment="Top" Width="300" Margin="20">
         <Grid.RowDefinitions>
             <RowDefinition Height="30"></RowDefinition>
             <RowDefinition Height="30"></RowDefinition>
             <RowDefinition Height="30"></RowDefinition>
             <RowDefinition Height="30"></RowDefinition>
             <RowDefinition Height="30"></RowDefinition>
         </Grid.RowDefinitions>
         <Grid.ColumnDefinitions>
             <ColumnDefinition Width="60"></ColumnDefinition>
             <ColumnDefinition Width="*"></ColumnDefinition>
         </Grid.ColumnDefinitions>
         <sdk:Label  HorizontalAlignment="Left" Content="图书编号:" VerticalAlignment="Center" Grid.Column="0" Grid.Row="0"/>
         <TextBox Text="{Binding ID}" Grid.Column="1" Grid.Row="0"></TextBox>
         <sdk:Label  HorizontalAlignment="Left" Content="图书名称:" VerticalAlignment="Center" Grid.Column="0" Grid.Row="1"/>
         <TextBox Text="{Binding Name}" Grid.Column="1" Grid.Row="1"></TextBox>
         <sdk:Label  HorizontalAlignment="Left" Content="图书作者:" VerticalAlignment="Center" Grid.Column="0" Grid.Row="2"/>
         <TextBox Text="{Binding Author}" Grid.Column="1" Grid.Row="2"></TextBox>
         <sdk:Label  HorizontalAlignment="Left" Content="图书价格:" VerticalAlignment="Center" Grid.Column="0" Grid.Row="3"/>
         <TextBox Text="{Binding Price}" Grid.Column="1" Grid.Row="3"></TextBox> 
            
         <Button Content="查询" Grid.Column="1" Grid.Row="4" Width="60" Height="23" Click="Button_Click"></Button>
     </Grid>
</Grid>

通过按钮执行调用WCF服务接口查询图书信息,按钮事件直接使用上面所写的图书门面类(BookFacade)的调用服务方法即可。

private void Button_Click(object sender, RoutedEventArgs e)
{
     try
     {
         ThreadPool.QueueUserWorkItem(delegate(object o)
         {
             BookViewModel viewModel = new BookViewModel();

             new BookFacade().GetBook(viewModel);

             Deployment.Current.Dispatcher.BeginInvoke(() => this.DataContext = viewModel);
         });
     }
     catch (Exception ex)
     {
         MessageBox.Show(ex.ToString());
     }
}

最终的运行如下图所示效果:

 


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@pclwef.cn

文章转载自:网络转载

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP