当前位置: 代码迷 >> Silverlight >> Silverlight兑现调用多个异步任务
  详细解决方案

Silverlight兑现调用多个异步任务

热度:9547   发布时间:2013-02-26 00:00:00.0
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();


这篇文章提供了一个不错的思路。这篇文章的评论中,有朋友也提到了Reactive Framework,我看了看,还没有找到很好的应用方法。这个Framework是一个很强大的东西,但在本文讨论的场景中具体该如何应用,如果有这方面研究的朋友,请不吝赐教
在这篇文章提供的简单模型基础上,我做了一些修改,并且也增加了一些更加实用的特性。共享出来给大家参考

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

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

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

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

完整源代码

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

?

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

#region Sample Code
??????? ////第一个任务
??????? //var task = new AsyncAction();
??????? //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.TaskName = "Hello,world";
??????? //??????? task.ActionResult.Message = "Test test";
??????? //??????? task.ActionResult.Result = a.Result;
??????? //??????? task.ActionResult.Status = ActionStatus.Success;
??????? //??????? task.OnCompleted();
??????? //??? };

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

??????? ////第二个任务
??????? //var task2 = new AsyncAction();
??????? //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.TaskName = "Hello,world";
??????? //??????? 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;
??????? //};
??????? ////将界面设置为忙碌
??????? //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>Jquery的appendTo和after区别和应用
??????? public DateTime EndTime { get; set; }
??? }
??? /// <summary>
??? /// 异步任务的接口
??? /// </summary>
??? public interface IAsyncAction
??? {
??????? void Execute();
??????? event EventHandler Completed;
??????? ActionResult PreActionResult { get; set; }
??????? ActionResult ActionResult { get; set; }
??? }
??? /// <summary>
??? /// 异步任务的实现类型
??? /// </summary>
??? public class AsyncAction : IAsyncAction
??? {
??????? 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>
??? public class AsyncActionRunner
??? {

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

??????? private readonly IEnumerator<IAsyncAction> _enumerator;
??????? public AsyncActionRunner(IEnumerator<IAsyncAction> enumerator)
??????????? : this()
??????? {
??????????? this._enumerator = enumerator;
??????? }

??????? public AsyncActionRunner(IEnumerable<IAsyncAction> tasks)
??????????? : this()
??????? {
??????????? _enumerator = tasks.GetEnumerator();
??????? }

??????? /// <summary>
??????? /// 完成事件及处理方法
??????? /// </summary>
??????? public event EventHandler Completed;
??????? /// <summary>
??????? /// 保存所有任务的执行结果
??????? /// </summary>
??????? public List<ActionResult> TaskResults { get; private set; }
??????? /// <summary>
??????? /// 临时保存的当前任务的执行结果
??????? /// </summary>
??????? private ActionResult tmp = null;
??????? /// <summary>
??????? /// 执行所有任务
??????? /// </summary>
??????? public void Execute()
??????? {
??????????? if(this._enumerator.MoveNext())
??????????? {
??????????????? this._enumerator.Current.Completed += (sender, args) =>
??????????????? {
??????????????????? tmp = ((IAsyncAction)sender).ActionResult;
??????????????????? tmp.EndTime = DateTime.Now;
??????????????????? TaskResults.Add(tmp);
??????????????????? this.Execute();
??????????????? };
??????????????? this._enumerator.Current.PreActionResult = tmp;
??????????????? this._enumerator.Current.Execute();
??????????? }Android 得到地理位置并分析出具体城市
??????????? else
??????????? {
??????????????? var completed = this.Completed;
??????????????? if(completed != null)
??????????????? {
??????????????????? completed(this, EventArgs.Empty);
??????????????? }
??????????? }
??????? }
??? }
}

  相关解决方案