好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

使用Task简化Silverlight调用Wcf(续)

使用Task简化Silverlight调用Wcf(续)

上一篇 使用Task简化Silverlight调用Wcf 介绍了Silverlight下使用Task的一些方法,这篇继续改进一下。

改进生成工具的生成的方法

上次生成的代码如下,这些TaskAsync只是简单的包装一下Wcf的begin和end方法:

?

public   Task DoWorkTaskAsync()

{

     return   Task.Factory.FromAsync( this .Channel.BeginDoWork, this .Channel.EndDoWork, null );

}

public   Task<DateTime> GetSerivceTimeTaskAsync()

{

     return   Task<DateTime>.Factory.FromAsync( this .Channel.BeginGetSerivceTime, this .Channel.EndGetSerivceTime, null );

}

调用时需要手动去Wait():

?

private   void   OnGetTimeClick( object   sender, RoutedEventArgs e)

{

     ThreadPool.QueueUserWorkItem(s =>

     {

         var task = _systemServiceClient.GetSerivceTimeTaskAsync();

         task.Wait();

         Dispatcher.BeginInvoke(() =>

         {

             MessageBox.Show(task.Result.ToString());

         });

     });

}

这次生成的方法连task1.Wait(); 也包含了,多生成一个方法来Wait:

?

public   Task DoWorkTaskAsync()

{

     return   Task.Factory.FromAsync( this .Channel.BeginDoWork, this .Channel.EndDoWork, null );

}

public   void   DoWork()

{

     var task = DoWorkTaskAsync();

     task.Wait();

}

 

public   Task<DateTime> GetSerivceTimeTaskAsync()

{

     return   Task<DateTime>.Factory.FromAsync( this .Channel.BeginGetSerivceTime, this .Channel.EndGetSerivceTime, null );

}

public   DateTime GetSerivceTime()

{

     var task = GetSerivceTimeTaskAsync();

     task.Wait();

     return   task.Result;

}

这样调用包含Wait的方法就直接返回结果了,而不是返回Task,再去Wait():

?

private   void   OnGetTimeClick( object   sender, RoutedEventArgs e)

{

     ThreadPool.QueueUserWorkItem(s =>

     {

         var time = _systemServiceClient.GetSerivceTime();

         Dispatcher.BeginInvoke(() => MessageBox.Show(time.ToString()));

     });

}

UI同步技巧

调用Wcf和UI交互需要顺序进行是最平常的需求,这时需要与UI交互也有“同步”的能力。例如:

?

ThreadPool.QueueUserWorkItem(s =&gt;

{

     //调用Wcf

     var num = _systemServiceClient.GetNum(5);

     //UI对话框询问是否继续

     var result = childWin.ShowSync();

     if (result == false )

         return ;

 

     var time = _systemServiceClient.GetSerivceTime();

     .......

});

如果是UI线程的话是不可以这样阻塞的,然而这里是后台线程,阻塞也是没所谓的,所以可以使用下面的方法来阻塞线程,来模拟同步:

?

public   partial   class   TestChildWindow : ChildWindow

{

     private   readonly   ManualResetEvent _manualResetEvent;

 

     public   TestChildWindow()

     {

         InitializeComponent();

         _manualResetEvent = new   ManualResetEvent( false );

         Closed += (_, __) => _manualResetEvent.Set();

     }

 

     public   bool ? ShowSync()

     {

         if   (Dispatcher.CheckAccess())

             throw   new   InvalidOperationException( "ShowSync只能使用后台线程调用!" );

 

         Dispatcher.BeginInvoke(Show);

         _manualResetEvent.Reset();

         _manualResetEvent.WaitOne();

         return   DialogResult;

     }

     .........

}

这里使用 ManualResetEvent 类来等待,打开窗体后马上阻塞,直到子窗体Closed时通知结束,实现”同步“。

这里注意ShowSync的Dispatcher.CheckAccess()判断,明确只能再后台线程里调用。

示例:

?

private   void   OnMultiTaskClick( object   sender, RoutedEventArgs e)

{

     var childWin = new   TestChildWindow();

     ThreadPool.QueueUserWorkItem(s =>

     {

         const   string   format = "Num:{1},{0}{2},{0}Time:{3},{0}UserCount:{4},{0}ChildWinResult:{5}" ;

         var num = _systemServiceClient.GetNum(5);

         var str = _systemServiceClient.SayHiTo(num.ToString());

     //这里是“同步”的

         var result = childWin.ShowSync();

 

         var time = _systemServiceClient.GetSerivceTime();

         var all = _userServiceClient.GetAll();

         var msg = string .Format(format, Environment.NewLine, num, str, time, all.Count, result);

         Dispatcher.BeginInvoke(() => MessageBox.Show(msg));

     });

}

工具和测试源码 http://www.cnblogs.com/lemontea/archive/2013/02/03/2890586.html

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于使用Task简化Silverlight调用Wcf(续)的详细内容...

  阅读:42次