zoukankan      html  css  js  c++  java
  • 使用Task简化Silverlight调用Wcf(续)

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

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    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():

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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():

    1
    2
    3
    4
    5
    6
    7
    8
    private void OnGetTimeClick(object sender, RoutedEventArgs e)
    {
        ThreadPool.QueueUserWorkItem(s =>
        {
            var time = _systemServiceClient.GetSerivceTime();
            Dispatcher.BeginInvoke(() => MessageBox.Show(time.ToString()));
        });
    }

    UI同步技巧

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ThreadPool.QueueUserWorkItem(s =&gt;
    {
        //调用Wcf
        var num = _systemServiceClient.GetNum(5);
        //UI对话框询问是否继续
        var result = childWin.ShowSync();
        if(result == false)
            return;
     
        var time = _systemServiceClient.GetSerivceTime();
        .......
    });

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    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()判断,明确只能再后台线程里调用。

    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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));
        });
    }

    image

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

  • 相关阅读:
    geoserver发布地图服务WMTS
    geoserver发布地图服务WMS
    geoserver安装部署步骤
    arcgis api 3.x for js 入门开发系列十四最近设施点路径分析(附源码下载)
    arcgis api 3.x for js 入门开发系列十三地图最短路径分析(附源码下载)
    cesium 之自定义气泡窗口 infoWindow 后续优化篇(附源码下载)
    arcgis api 3.x for js 入门开发系列十二地图打印GP服务(附源码下载)
    arcgis api 3.x for js 入门开发系列十一地图统计图(附源码下载)
    arcgis api 3.x for js 入门开发系列十叠加 SHP 图层(附源码下载)
    arcgis api 3.x for js入门开发系列九热力图效果(附源码下载)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2890719.html
Copyright © 2011-2022 走看看