轉帖|其它|編輯:郝浩|2011-08-30 15:25:13.000|閱讀 547 次
概述:本文主要講述一下在Silverlight中對多個異步任務的調用問題,希望對大家有幫助。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
這是一個常見的問題,由于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();
為了解決這個問題,我自己也想過一些辦法,同時參考了張志敏的如下文章
//www.cnblogs.com/beginor/archive/2010/12/24/1915910.html
這篇文章提供了一個不錯的思路。這篇文章的評論中,有朋友也提到了Reactive Framework,我看了看,還沒有找到很好的應用方法。這個Framework是一個很強大的東西,但在本文討論的場景中具體該如何應用,如果有這方面研究的朋友,請不吝賜教
在這篇文章提供的簡單模型基礎上,我做了一些修改,并且也增加了一些更加實用的特性。共享出來給大家參考
添加和改進的功能主要是:
1.使用更加便捷(原先是用IEnumerator去構造Runner,現在提供了更多的支持,可以是一個Array,也可以是一個List等等,因為我們很多時候任務是動態構造出來的)
2.提供了任務結果反饋(ActionResult)的功能
3.提供了任務之間約束的功能,在每個任務里面都可以得到前置任務的信息
如何使用?
第一步:添加Nuget Package,關于什么是Nuget,請參考 //www.cnblogs.com/dudu/archive/2011/07/15/nuget.html
第二步,參考如下的范例代碼
運行效果
完整源代碼
如果你不想下載包,可以直接復制這個代碼進行使用或者修改
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; }
}
}
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:博客園