Mgen Srt工程1.0 .NET/iOS版发布
返回目录
0. 简介和下载
版本信息
版本 | 支持平台 | 发布时间 |
1.0 | .NET 2 / iOS | 2014-02-05 |
Srt工程用来支持创建一种可控制,有信息反馈的任务模型,比如支持暂停,停止,Progress和Log汇报的任务模型。在1.0版本中,只支持单个任务的执行,在之后的版本会加入对符合任务以及并发符合任务的支持。
如下图,在.NET(Windows桌面)和iOS中运行的Srt工程Demo:
当前版本的源代码下载
下载页面
注意:链接是微软SkyDrive页面,下载时请用浏览器直接下载,用某些下载工具可能无法下载
.NET版类库环境:.NET Framework 2.0
.NET版源代码环境:Microsoft Visual Studio Express 2013 for Windows Desktop
iOS版源代码环境:Xcode 5
返回目录
1. 状态和状态修饰数据
每个执行任务都有四个状态,下面是状态的描述和状态切换的关系。
状态名称 | 进入途径 |
未开始 | 1. 所有任务的最初状态。 2. 已完成任务被重置后。 |
正在执行 | 1. 未开始状态的任务执行后。 |
已完成 | 1. 正在执行任务执行完毕后。 2. 正在执行任务被停止后。 3. 暂停的任务被停止后。 |
暂停 | 1. 正在执行的任务被暂停后。 |
而状态修饰数据是指在特定状态下才会生效的修饰数据。通常情况下是针对在已完成状态中。比如已完成具体是成功执行完毕?还是用户取消?还是遇到意外错误?成功完成后的返回值是?这些问题都可以通过访问状态修饰数据来找到结果。
任务状态对应的是SrtStatus枚举类型:
.NET:
public enum SrtStatus
{
Unstarted, Running, Completed, Paused
}
iOS:
typedef NS_ENUM(NSInteger, SrtStatus)
{
SrtStatusUnstarted,
SrtStatusRunning,
SrtStatusCompleted,
SrtStatusPaused
};
返回目录
2. 基础任务类型:SrtItem
这里主要以.NET的类型来讲解,iOS对应的类型和.NET类型的命名完全一致,用法也一样。
整个Srt工程的基础任务类型就是SrtItem,他是一个抽象类型,首先包含上面讲的任务的状态:Status属性。其次还包含一些特定的状态修饰数据,如下:
属性名称 | 描述 |
IsCancelled | 是否被取消 |
Error | 任务执行错误信息 |
HasError | 是否有错误信息 |
Result | 任务执行结果(该值如果存在的话,通常代表人物已成功完成) |
接下来就是任务的操作方法,如下:
方法名称 | 描述 |
Start | 开始 |
Stop | 停止 |
Pause | 暂停 |
Remuse | 继续 |
ResetStatus | 重置状态 |
这些方法都是供外部直接调用,且方法结果都返回bool。true则是调用成功,状态值会被切换,false则代表调用失败,原因就是没有按照上面讲的状态值切换规则。比如在未开始状态时调用Pause,结果肯定是false,因为只有正在运行状态中的任务才可以暂停。
注意最下面还有个ResetStatus方法,他会重置所有内部状态,把任务切换到未开始状态。
对于状态改变,.NET中的SrtItem提供StatusChanged事件:
public event EventHandler StatusChanged;
iOS中则是statusChanged Block属性:
@property (nonatomic, strong) void(^statusChanged)(id sender);
对于Start/Pause/Resume/Stop这种方法调用,SrtItem中还有protected修饰的OnXXX方法执行,当然这个protected修饰符只针对.NET,Objective-C中没有,在Objective-C中,方法要么有,要么就是没有。至于ResetStatus方法,.NET中也是virtual的,而Objective-C中任何方法都是可改写的。所以在具体执行上,不同平台因为有不同语言会有一些细小的差异,但是不会影响很大的。
返回目录
3. 内部状态和进度的执行
SrtItem抽象支持暂停停止等操作,但是具体怎样执行?下面我们来看看。
SrtItem的CanPause和CanStop属性来表示任务是否支持暂停或者停止,默认当然是false,如果你的任务支持暂停和停止的话,首先改写这两个属性,并返回true。
接下来就是具体的任务执行了,任务执行是通过改写Run方法的,在执行中,你需要轮循检查TerminationRequest属性,这个属性代表是否有暂停或者停止请求操作,枚举类型定义:
public enum SrtTerminationRequest
{
None, Pause, Stop
}
当检查到TerminationReqeust属性值不是None时,则代表有暂停或者停止请求,比如如果是暂停的话,存储当前的状态(可以通过SrtItem的Tag属性),然后理解结束任务。
对于继续操作(也就是Resume方法调用后),SrtItem还会调用Run方法的,所以如果支持暂停操作的话,Run方法开始需要判断有没有缓存的状态,如果有的话,继续从这个状态执行任务。
另一个需要注意的是,在Run方法执行完毕前,必须调用CommitXXX方法来告诉Srt工程任务当前的状态,具体有如下方法:
CommitCompletion代表任务结束,可以设置返回值或者错误信息。(如果没有返回值也没有错误信息,那么可以不去调用CommitCompletion方法,SrtItem的默认返回状态就是这样的)
CommitTermination代表任务终止,也就是因暂停或者停止而结束。
来看Demo工程中的示例任务的Run方法执行(代码中会有一些Progress和Log的信息汇报,这个在下面会有讲到)。
.NET:
protected override void Run(SrtOption option)
{
int startIdx = 0;
//尝试读取暂停前的进度(如果有的话)
if (Tag != null)
startIdx = (int)Tag;
for (int i = startIdx; i < 10; i++)
{
//检查是否有取消或者暂停操作挂起
var cancelReq = TerminationRequest;
if (cancelReq != SrtTerminationRequest.None)
{
//暂停操作,缓存当前进度
if(cancelReq == SrtTerminationRequest.Pause)
{
Tag = i;
}
CommitTermination(cancelReq);
return;
}
//是否需要汇报进度
if(option.ProgressEnabled)
{
var progInfo = new SrtProgressInfo();
progInfo.Progress = (double)i / 10;
progInfo.Message = String.Format("第{0}个过程", i + 1);
//报告进度
OnProgressChanged(progInfo);
}
//模拟实际耗时操作
System.Threading.Thread.Sleep(random.Next(1000));
//是否需要Log
if(option.LoggingEnabled)
{
var logInfo = new SrtLogInfo();
logInfo.Level = 0;
logInfo.Message = String.Format("PROCESS {0}", i + 1);
//Log
OnLog(logInfo);
}
}
}
iOS:
- (void)run:(SrtOption *)option
{
//尝试读取暂停前的进度(如果有的话)
NSNumber *startIdx = (NSNumber*)self.tag;
for (int i = [startIdx intValue]; i < 10; i++)
{
//检查是否有取消或者暂停操作挂起
SrtTerminationRequest cancelReq = self.terminationRequest;
if (cancelReq != SrtTerminationRequestNone)
{
//暂停操作,缓存当前进度
if (cancelReq == SrtTerminationRequestPause)
{
self.tag = @(i);
}
[self commitTermination:cancelReq];
return;
}
//是否需要汇报进度
if (option.progressEnabled)
{
SrtProgressInfo *progInfo = [SrtProgressInfo new];
progInfo.progress = (double)i / 10;
progInfo.message = [NSString stringWithFormat:@"第%d个过程", i + 1];
//报告进度
[self onProgressChanged:progInfo];
}
//模拟实际耗时操作
[NSThread sleepForTimeInterval:drand48() + 0.1];
//是否需要Log
if (option.loggingEnabled)
{
SrtLogInfo *logInfo = [SrtLogInfo new];
logInfo.level = 0;
logInfo.message = [NSString stringWithFormat:@"PROCESS: %d", i + 1];
//Log
[self onLog:logInfo];
}
}
}
返回目录
4. Progress和Log
很简单,这些事用来在任务执行过程中进行进度和日志的汇报。Progress信息是通过创建一个SrtProgressInfo对象,Log信息通过创建一个SrtLogInfo对象。创建好这些对象后,设置相应的属性,然后就是调用SrtItem的OnProgressChanged和OnLog方法来汇报这个信息。
至于事件响应上,.NET中的SrtItem定义了ProgressChanged和Log事件:
public event EventHandler<SrtLogInfo> Log;
public event EventHandler<SrtProgressInfo> ProgressChanged;
iOS中的SrtItem则是定义了两个Block属性:
@property (nonatomic, strong) void(^progressChanged)(id sender, SrtProgressInfo *info);
@property (nonatomic, strong) void(^log)(id sender, SrtLogInfo *info);
示例代码就可以参考上面的Run方法执行,不过上面代码可以看到,在汇报信息前会判断参数中SrtOption中的ProgressEnabled和LoggingEnabled属性,如果为true的话,才进行进度或者日志的汇报。
这个SrtOption对象,很简单,代表任务在执行过程中的选项,目前有三个属性:
IsAsync代表是否异步执行。LoggingEnabled和ProgressEnabled就是上面讲的,是否进行Log或者Progress信息的汇报。
所以最好先判断这些属性再进行信息的汇报,因为如果调用方不需要这些信息,任务本身也没必要浪费CPU和内存来汇报相应的信息了。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。