轉(zhuǎn)帖|其它|編輯:郝浩|2011-08-30 15:25:13.000|閱讀 560 次
概述:本文主要講述一下在Silverlight中對(duì)多個(gè)異步任務(wù)的調(diào)用問(wèn)題,希望對(duì)大家有幫助。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門(mén)軟控件火熱銷售中 >>
這是一個(gè)常見(jiàn)的問(wèn)題,由于Silverlight只支持異步調(diào)用后臺(tái)的服務(wù),而如果有多個(gè)任務(wù)的話,可能就很麻煩,往往就是要在一個(gè)異步任務(wù)結(jié)束事件中去調(diào)用另外一個(gè)任務(wù),以此類推。典型的問(wèn)題就是,代碼很復(fù)雜,而且?guī)缀鹾茈y維護(hù)。看看下面的代碼吧
//傳統(tǒng)的多個(gè)異步任務(wù)的調(diào)用方法,必須是一層一層嵌套的方式
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();
為了解決這個(gè)問(wèn)題,我自己也想過(guò)一些辦法,同時(shí)參考了張志敏的如下文章
//www.cnblogs.com/beginor/archive/2010/12/24/1915910.html
這篇文章提供了一個(gè)不錯(cuò)的思路。這篇文章的評(píng)論中,有朋友也提到了Reactive Framework,我看了看,還沒(méi)有找到很好的應(yīng)用方法。這個(gè)Framework是一個(gè)很強(qiáng)大的東西,但在本文討論的場(chǎng)景中具體該如何應(yīng)用,如果有這方面研究的朋友,請(qǐng)不吝賜教
在這篇文章提供的簡(jiǎn)單模型基礎(chǔ)上,我做了一些修改,并且也增加了一些更加實(shí)用的特性。共享出來(lái)給大家參考
添加和改進(jìn)的功能主要是:
1.使用更加便捷(原先是用IEnumerator去構(gòu)造Runner,現(xiàn)在提供了更多的支持,可以是一個(gè)Array,也可以是一個(gè)List等等,因?yàn)槲覀兒芏鄷r(shí)候任務(wù)是動(dòng)態(tài)構(gòu)造出來(lái)的)
2.提供了任務(wù)結(jié)果反饋(ActionResult)的功能
3.提供了任務(wù)之間約束的功能,在每個(gè)任務(wù)里面都可以得到前置任務(wù)的信息
如何使用?
第一步:添加Nuget Package,關(guān)于什么是Nuget,請(qǐng)參考 //www.cnblogs.com/dudu/archive/2011/07/15/nuget.html
第二步,參考如下的范例代碼
運(yùn)行效果
完整源代碼
如果你不想下載包,可以直接復(fù)制這個(gè)代碼進(jìn)行使用或者修改
using System;
using System.Collections.Generic;
using System.Linq;
/*
* 這個(gè)設(shè)計(jì)針對(duì)在Silverlight中經(jīng)常需要對(duì)多個(gè)遠(yuǎn)程服務(wù)進(jìn)行調(diào)用,而且我們可能需要讓這些任務(wù)之間有固定的順序,同時(shí)還希望能夠在任務(wù)之間傳遞任務(wù)狀態(tài),還支持進(jìn)度匯報(bào)的功能
* 作者:陳希章
* 時(shí)間:2011年8月30日
* 反饋:ares@xizhang.com
*/
#region Sample Code
////第一個(gè)任務(wù)
//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);
////第二個(gè)任務(wù)
//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);
////構(gòu)造Runner
//var runner = new AsyncActionRunner(new[] { task, task2 });
////注冊(cè)完成事件
//runner.Completed += (o, a) =>
//{
// //將界面設(shè)置為空閑
// busyIndicator.IsBusy = false;
// //顯示所有任務(wù)的執(zhí)行結(jié)果
// 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);
//};
////將界面設(shè)置為忙碌
//busyIndicator.IsBusy = true;
////執(zhí)行
//runner.Execute();
#endregion
namespace System
{
/// <summary>
/// 這個(gè)枚舉記錄了任務(wù)的狀態(tài),默認(rèn)為Ready
/// </summary>
public enum ActionStatus
{
Ready,//準(zhǔn)備好,如果最后檢查仍然為這個(gè)狀態(tài),則通常表示該任務(wù)被跳過(guò)了
Success,//成功
Failure,//失敗
Completed//完成
}
/// <summary>
/// 這個(gè)記錄了任務(wù)的結(jié)果
/// </summary>
public class ActionResult
{
public ActionResult()
{
Status = ActionStatus.Ready;//默認(rèn)為ready
StartTime = DateTime.Now;
}
/// <summary>
/// 任務(wù)名稱
/// </summary>
public string TaskName { get; set; }
/// <summary>
/// 狀態(tài)
/// </summary>
public ActionStatus Status { get; set; }
/// <summary>
/// 消息
/// </summary>
public string Message { get; set; }
/// <summary>
/// 任務(wù)結(jié)果
/// </summary>
public object Result { get; set; }
/// <summary>
/// 開(kāi)始時(shí)間
/// </summary>
public DateTime StartTime { get; set; }
/// <summary>
/// 結(jié)束時(shí)間
/// </summary>
public DateTime EndTime { get; set; }
}
/// <summary>
/// 異步任務(wù)的接口
/// </summary>
public interface IAsyncAction
{
void Execute();
event EventHandler Completed;
ActionResult PreActionResult { get; set; }
ActionResult ActionResult { get; set; }
string TaskName { get; set; }
}
/// <summary>
/// 異步任務(wù)的實(shí)現(xiàn)類型
/// </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>
/// 設(shè)置要執(zhí)行的操作
/// </summary>
/// <param name="action">操作</param>
/// <param name="autoComplete">是否自動(dòng)完成</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>
/// 前置任務(wù)的結(jié)果,添加這個(gè)功能目的是,可能多個(gè)任務(wù)之間互相有所依賴,例如某個(gè)任務(wù)要根據(jù)前面任務(wù)的情況決定是否執(zhí)行
/// </summary>
public ActionResult PreActionResult { get; set; }
/// <summary>
/// 當(dāng)前任務(wù)的結(jié)果
/// </summary>
public ActionResult ActionResult { get; set; }
/// <summary>
/// 任務(wù)名稱
/// </summary>
private string taskName = string.Empty;
public string TaskName
{
get
{
return taskName;
}
set
{
taskName = value; ActionResult.TaskName = value;
}
}
}
/// <summary>
/// 任務(wù)運(yùn)行器
/// </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>
/// 進(jìn)度發(fā)生更改時(shí)發(fā)生
/// </summary>
public event EventHandler<ProgressEventArgs> ProgressChanged;
/// <summary>
/// 保存所有任務(wù)的執(zhí)行結(jié)果
/// </summary>
public List<ActionResult> TaskResults { get; private set; }
/// <summary>
/// 臨時(shí)保存的當(dāng)前任務(wù)的執(zhí)行結(jié)果
/// </summary>
private ActionResult tmp = null;
private int index = 1;
/// <summary>
/// 執(zhí)行所有任務(wù)
/// </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;//將進(jìn)度復(fù)位
var completed = this.Completed;
if(completed != null)
{
completed(this, EventArgs.Empty);
}
}
}
}
/// <summary>
/// 進(jìn)度事件的參數(shù)
/// </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; }
}
}
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@ke049m.cn
文章轉(zhuǎn)載自:博客園