zoukankan      html  css  js  c++  java
  • Silverlight同步(Synchronous)调用WCF服务

      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 { getset; }
        
    public string Name { getset; }
        
    public string Author { getset; }
        
    public double Price { getset; }
    }

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

    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(
    thisnew 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 { getset; }
    }
    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());
        }
    }

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

      

      

    版权说明

      本文属原创文章,欢迎转载且注明文章出处,其版权归作者和博客园共有。为了保存作者的创作热情,请在转载后的明显位置标记本文出处。  

      作      者:Beniao

     文章出处:http://beniao.cnblogs.com/  或  http://www.cnblogs.com/

  • 相关阅读:
    How to build Linux system from kernel to UI layer
    Writing USB driver for Android
    Xposed Framework for Android 8.x Oreo is released (in beta)
    Linux Smartphone Operating Systems You Can Install Today
    Librem 5 Leads New Wave of Open Source Mobile Linux Contenders
    GUADEC: porting GNOME to Android
    Librem 5 – A Security and Privacy Focused Phone
    GNOME and KDE Join Librem 5 Linux Smartphone Party
    Purism计划推出安全开源的Linux Librem 5智能手机
    国产系统之殇:你知道的这些系统都是国外的
  • 原文地址:https://www.cnblogs.com/beniao/p/1929639.html
Copyright © 2011-2022 走看看