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和内存来汇报相应的信息了。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。