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

  • 相关阅读:
    自动化CodeReview
    10个有关RESTful API良好设计的最佳实践
    ASP.NET Core 获取控制器上的自定义属性
    [转] Autofac创建实例的方法总结
    PetaPoco
    LogViewer
    hdoj:2047
    hdoj:2046
    hdoj:2045
    hdoj:2044
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2890719.html
Copyright © 2011-2022 走看看