• 在Silverlight中对多个异步任务的调用


    这是一个常见的问题,由于Silverlight只支持异步调用后台的服务,而如果有多个任务的话,可能就很麻烦,往往就是要在一个异步任务结束事件中去调用另外一个任务,以此类推。典型的问题就是,代码很复杂,而且几乎很难维护。看看下面的代码吧

                //传统的多个异步任务的调用方法,必须是一层一层嵌套的方式
                
                var proxy = new ServiceReference1.WebService1SoapClient();
                proxy.Endpoint.Address = new System.ServiceModel.EndpointAddress(
                    new Uri(App.Current.Host.Source, "../WebService1.asmx"));
    
                proxy.HelloWorldCompleted += (o, a) =>
                {
                    
                    proxy.GetEmployeeCompleted += (o1, a1) =>
                    {
                        proxy.GetCustomersCompleted += (o2, a1) =>
                        {
    
                        };
                        proxy.GetCustomersAsync();
                    };
    
                    proxy.GetEmployeeAsync();
                };
                proxy.HelloWorldAsync();

    为了解决这个问题,我自己也想过一些办法,同时参考了张志敏的如下文章

    http://www.cnblogs.com/beginor/archive/2010/12/24/1915910.html

    这篇文章提供了一个不错的思路。这篇文章的评论中,有朋友也提到了Reactive Framework,我看了看,还没有找到很好的应用方法。这个Framework是一个很强大的东西,但在本文讨论的场景中具体该如何应用,如果有这方面研究的朋友,请不吝赐教

    在这篇文章提供的简单模型基础上,我做了一些修改,并且也增加了一些更加实用的特性。共享出来给大家参考

    添加和改进的功能主要是:

    1.使用更加便捷(原先是用IEnumerator去构造Runner,现在提供了更多的支持,可以是一个Array,也可以是一个List等等,因为我们很多时候任务是动态构造出来的)

    2.提供了任务结果反馈(ActionResult)的功能

    3.提供了任务之间约束的功能,在每个任务里面都可以得到前置任务的信息

    如何使用?

    第一步:添加Nuget Package,关于什么是Nuget,请参考 http://www.cnblogs.com/dudu/archive/2011/07/15/nuget.html

    image

    第二步,参考如下的范例代码

    运行效果

    image

    完整源代码

    如果你不想下载包,可以直接复制这个代码进行使用或者修改

    using System;
    using System.Collections.Generic;
    using System.Linq;
    /*
     * 这个设计针对在Silverlight中经常需要对多个远程服务进行调用,而且我们可能需要让这些任务之间有固定的顺序,同时还希望能够在任务之间传递任务状态,还支持进度汇报的功能
     * 作者:陈希章
     * 时间:2011年8月30日
     * 反馈:ares@xizhang.com
     
    */

    #region Sample Code
            
    ////第一个任务
            //var task = new AsyncAction("Task 1");
            
    //task.SetAction(() =>
            
    //{
            
    //    var proxy = new ServiceReference1.WebService1SoapClient();
            
    //    proxy.Endpoint.Address = new System.ServiceModel.EndpointAddress(
            
    //        new Uri(App.Current.Host.Source, "../WebService1.asmx"));

            
    //    proxy.HelloWorldCompleted += (o, a) =>
            
    //    {
            
    //        task.ActionResult.Message = "Test test";
            
    //        task.ActionResult.Result = a.Result;
            
    //        task.ActionResult.Status = ActionStatus.Success;
            
    //        task.OnCompleted();
            
    //    };

            
    //    proxy.HelloWorldAsync();
            
    //}, true);

            
    ////第二个任务
            //var task2 = new AsyncAction("Task 2");
            
    //task2.SetAction(() =>
            
    //{
            
    //    var proxy = new ServiceReference1.WebService1SoapClient();
            
    //    proxy.Endpoint.Address = new System.ServiceModel.EndpointAddress(
            
    //        new Uri(App.Current.Host.Source, "../WebService1.asmx"));

            
    //    proxy.HelloWorldCompleted += (o, a) =>
            
    //    {
            
    //        task2.ActionResult.Message = "Test test";
            
    //        task2.ActionResult.Result = a.Result;
            
    //        task2.ActionResult.Status = ActionStatus.Success;
            
    //        task2.OnCompleted();
            
    //    };
            
    //    proxy.HelloWorldAsync();
            
    //}, true);

            
    ////构造Runner
            //var runner = new AsyncActionRunner(new[] { task, task2 });

            
    ////注册完成事件
            //runner.Completed += (o, a) =>
            
    //{
            
    //    //将界面设置为空闲
            
    //    busyIndicator.IsBusy = false;
            
    //    //显示所有任务的执行结果
            
    //    dgResult.ItemsSource = runner.TaskResults;
            
    //};

            
    //runner.ProgressChanged += (o, a) =>
            
    //{
            
    //    busyIndicator.BusyContent = string.Format("Current Step :{0}, Percent:{1:p}, Name:{2},Status:{3}", a.Current, a.Percent, a.ActionResult.TaskName, a.ActionResult.Status);
            
    //};

            
    ////将界面设置为忙碌
            //busyIndicator.IsBusy = true;

            
    ////执行
            //runner.Execute();
    #endregion


    namespace System
    {
        
    /// <summary>
        
    /// 这个枚举记录了任务的状态,默认为Ready
        
    /// </summary>
        public enum ActionStatus
        {
            Ready,
    //准备好,如果最后检查仍然为这个状态,则通常表示该任务被跳过了
            Success,//成功
            Failure,//失败
            Completed//完成
        }
        
    /// <summary>
        
    /// 这个记录了任务的结果
        
    /// </summary>
        public class ActionResult
        {
            
    public ActionResult()
            {
                Status 
    = ActionStatus.Ready;//默认为ready
                StartTime = DateTime.Now;
            }
            
    /// <summary>
            
    /// 任务名称
            
    /// </summary>
            public string TaskName { getset; }
            
    /// <summary>
            
    /// 状态
            
    /// </summary>
            public ActionStatus Status { getset; }
            
    /// <summary>
            
    /// 消息
            
    /// </summary>
            public string Message { getset; }
            
    /// <summary>
            
    /// 任务结果
            
    /// </summary>
            public object Result { getset; }

            
    /// <summary>
            
    /// 开始时间
            
    /// </summary>
            public DateTime StartTime { getset; }
            
    /// <summary>
            
    /// 结束时间
            
    /// </summary>
            public DateTime EndTime { getset; }
        }
        
    /// <summary>
        
    /// 异步任务的接口
        
    /// </summary>
        public interface IAsyncAction
        {
            
    void Execute();
            
    event EventHandler Completed;
            ActionResult PreActionResult { 
    getset; }
            ActionResult ActionResult { 
    getset; }

            
    string TaskName { getset; }
        }
        
    /// <summary>
        
    /// 异步任务的实现类型
        
    /// </summary>
        public class AsyncAction : IAsyncAction
        {
            
    public AsyncAction(string name):this()
            {
                TaskName 
    = name;
            }

            
    public AsyncAction()
            {
                ActionResult 
    = new ActionResult();
            }

            
    private bool AutoComplete = false;
            
    private Action Action { getset; }
            
    /// <summary>
            
    /// 设置要执行的操作
            
    /// </summary>
            
    /// <param name="action">操作</param>
            
    /// <param name="autoComplete">是否自动完成</param>
            public void SetAction(Action action, bool autoComplete)
            {
                Action 
    = action;
                AutoComplete 
    = autoComplete;
            }


            
    public virtual void Execute()
            {
                
    if(Action != null)
                {
                    ActionResult.StartTime 
    = DateTime.Now;
                    Action();
                    
    if(!AutoComplete)
                        OnCompleted();
                }
            }

            
    public event EventHandler Completed;
            
    public void OnCompleted()
            {
                var completed 
    = this.Completed;
                
    if(completed != null)
                {
                    completed(
    this, EventArgs.Empty);
                }
            }
            
    /// <summary>
            
    /// 前置任务的结果,添加这个功能目的是,可能多个任务之间互相有所依赖,例如某个任务要根据前面任务的情况决定是否执行
            
    /// </summary>
            public ActionResult PreActionResult { getset; }
            
    /// <summary>
            
    /// 当前任务的结果
            
    /// </summary>
            public ActionResult ActionResult { getset; }

            
    /// <summary>
            
    /// 任务名称
            
    /// </summary>
            private string taskName = string.Empty;
            
    public string TaskName
            {
                
    get
                {
                    
    return taskName;
                }
                
    set
                {
                    taskName 
    = value; ActionResult.TaskName = value;
                }
            }
        }


        
    /// <summary>
        
    /// 任务运行器
        
    /// </summary>
        public class AsyncActionRunner
        {

            
    public AsyncActionRunner()
            {
                TaskResults 
    = new List<ActionResult>();

            }

            
    private readonly IEnumerator<IAsyncAction> _enumerator;
            
    private int taskCount = 0;
            
    //public AsyncActionRunner(IEnumerator<IAsyncAction> enumerator)
            
    //    : this()
            
    //{
            
    //    this._enumerator = enumerator;
            
    //}

            
    public AsyncActionRunner(IList<IAsyncAction> tasks)
                : 
    this()
            {
                taskCount 
    = tasks.Count();
                _enumerator 
    = tasks.GetEnumerator();
            }

            
    /// <summary>
            
    /// 完成事件及处理方法
            
    /// </summary>
            public event EventHandler Completed;
            
    /// <summary>
            
    /// 进度发生更改时发生
            
    /// </summary>
            public event EventHandler<ProgressEventArgs> ProgressChanged;


            
    /// <summary>
            
    /// 保存所有任务的执行结果
            
    /// </summary>
            public List<ActionResult> TaskResults { getprivate set; }
            
    /// <summary>
            
    /// 临时保存的当前任务的执行结果
            
    /// </summary>
            private ActionResult tmp = null;


            
    private int index = 1;
            
    /// <summary>
            
    /// 执行所有任务
            
    /// </summary>
            public void Execute()
            {
                
    if(this._enumerator.MoveNext())
                {
                    var current 
    = this._enumerator.Current;
                    tmp 
    = current.ActionResult;
                    var ci 
    = index++;

                    current.Completed 
    += (sender, args) =>
                    {
                        tmp 
    = ((IAsyncAction)sender).ActionResult;
                        tmp.EndTime 
    = DateTime.Now;
                        TaskResults.Add(tmp);

                        
    if(ProgressChanged != null)
                        {
                            ProgressChanged(
    thisnew ProgressEventArgs(ci, (double)ci / taskCount, tmp));
                        }

                        
    this.Execute();

                    };
                    current.PreActionResult 
    = tmp;
                    current.Execute();

                    ProgressChanged(
    thisnew ProgressEventArgs(ci, (double)ci / taskCount, tmp));

                }
                
    else
                {
                    index 
    = 1;//将进度复位
                    var completed = this.Completed;
                    
    if(completed != null)
                    {
                        completed(
    this, EventArgs.Empty);
                    }
                }
            }
        }

        
    /// <summary>
        
    /// 进度事件的参数
        
    /// </summary>
        public class ProgressEventArgs : EventArgs
        {
            
    public int Current { getset; }
            
    public ActionResult ActionResult { getset; }
            
    public ProgressEventArgs(int current, double percent, ActionResult result)
            {
                
    this.Current = current;
                ActionResult 
    = result;
                Percent 
    = percent;
            }
            
    public double Percent { getset; }
        }
    }
  • 相关阅读:
    桶排序
    向控件添加变量之后,类中多了什么?
    atan2&sin
    Bug(1)
    十六进制转化二进制[c]
    接口性能分析与优化
    记一次内存泄漏DUMP分析
    偏移二分查找
    iOS开发——自定义密码输入键盘
    iOS开发——手机号,密码,邮箱,身份证号,中文判断
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/2159124.html
Copyright © 2020-2023  润新知