在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 {  get set ; }
        
///   <summary>
        
///  状态
        
///   </summary>
         public  ActionStatus Status {  get set ; }
        
///   <summary>
        
///  消息
        
///   </summary>
         public   string  Message {  get set ; }
        
///   <summary>
        
///  任务结果
        
///   </summary>
         public   object  Result {  get set ; }

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

        
string  TaskName {  get set ; }
    }
    
///   <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 {  get set ; }
        
///   <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 {  get set ; }
        
///   <summary>
        
///  当前任务的结果
        
///   </summary>
         public  ActionResult ActionResult {  get set ; }

        
///   <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 {  get private   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(
this new  ProgressEventArgs(ci, ( double )ci  /  taskCount, tmp));
                    }

                    
this .Execute();

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

                ProgressChanged(
this new  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 {  get set ; }
        
public  ActionResult ActionResult {  get set ; }
        
public  ProgressEventArgs( int  current,  double  percent, ActionResult result)
        {
            
this .Current  =  current;
            ActionResult 
=  result;
            Percent 
=  percent;
        }
        
public   double  Percent {  get set ; }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值