C#库用户手册

Step 1. 通过 NuGet 下载 Fawdlstty.SMLite

Step 2. 定义两个枚举类,分别代表所有的状态与所有的触发器

enum MyState { Rest, Ready, Reading, Writing };
enum MyTrigger { Run, Close, Read, FinishRead, Write, FinishWrite };

Step 3. 定义状态机变量,模板为两个枚举类,参数为初始值

var _smb = new SMLiteBuilder<MyState, MyTrigger> ();

Step 4. 定义状态机的规则,指定具体的某个状态允许触发什么事件

_smb.Configure (MyState.Rest)

    // 如果状态由其他状态变成 MyState.Rest 状态,那么触发此方法,初始化状态机时指定的初始值不触发此方法
    .OnEntry (() => Console.WriteLine ("entry Rest"))

    // 如果状态由 MyState.Rest 状态变成其他状态,那么触发此方法
    .OnLeave (() => Console.WriteLine ("leave Rest"))

    // 如果触发 MyTrigger.Run,则将状态改为 MyState.Ready
    .WhenChangeTo (MyTrigger.Run, MyState.Ready)

    // 如果触发 MyTrigger.Run,忽略
    .WhenIgnore (MyTrigger.Close)

    // 如果触发 MyTrigger.Read,则调用回调函数,并将状态调整为返回值
    .WhenFunc (MyTrigger.Read, (MyState _state, MyTrigger _trigger) => {
        Console.WriteLine ("call WhenFunc callback");
        return MyState.Ready;
    })

    // 如果触发 MyTrigger.FinishRead,则调用回调函数,并将状态调整为返回值
    // 需注意,触发时候需传入参数,数量与类型必须完全匹配,否则抛异常
    .WhenFunc (MyTrigger.FinishRead, (MyState _state, MyTrigger _trigger, string _param) => {
        Console.WriteLine ($"call WhenFunc callback with param [{_param}]");
        return MyState.Ready;
    })

    // 如果触发 MyTrigger.Write,则调用回调函数(触发此方法回调不调整返回值)
    .WhenAction (MyTrigger.Write, (MyState _state, MyTrigger _trigger) => {
        Console.WriteLine ("call WhenAction callback");
    })

    // 如果触发 MyTrigger.FinishWrite,则调用回调函数(触发此方法回调不调整返回值)
    // 需注意,触发时候需传入参数,数量与类型必须完全匹配,否则抛异常
    .WhenAction (MyTrigger.FinishWrite, (MyState _state, MyTrigger _trigger, string _param) => {
        Console.WriteLine ($"call WhenAction callback with param [{_param}]");
    });

同一个状态下,如果遇到同样的触发器,最多只允许定义一种处理方式,上面代码对定义的触发事件有详细解释。如果不定义触发事件但遇到触发,那么抛异常。

Step 5. 下面开始真正使用到状态机

// 生成状态机
auto _sm = _smb.Build (MyState.Rest);

// 获取当前状态
Assert.AreEqual (_sm.State == MyState.Rest);

// 判断是否允许触发某一个事件
_sm.AllowTriggering (MyTrigger.Run);

// 触发一个事件
_sm.Triggering (MyTrigger.Run);

// 触发一个事件,并传入指定参数
_sm.Triggering (MyTrigger.Run, "hello");

// 强行修改当前状态,此操作将不会触发OnEntry、OnLeave事件
_sm.State = MyState.Rest;

Step 6. 如果用到异步

使用与上面非常相似,下面是指定异步触发回调函数

var _smb = new SMLiteBuilderAsync <MyState, MyTrigger> ();
_smb.Configure (MyState.Ready)

    // 与 OnEntry 效果一致,不过这函数指定异步方法,并且不能与 OnEntry 同时调用
    .OnEntryAsync (async () => {
        await Task.Yield ();
        Console.WriteLine ("entry Ready");
    })

    // 与 OnLeave 效果一致,不过这函数指定异步方法,并且不能与 OnLeave 同时调用
    .OnLeaveAsync (async () => {
        await Task.Yield ();
        Console.WriteLine ("leave Ready");
    })

    // 效果与 WhenFunc 一致,不过这函数指定异步方法
    .WhenFuncAsync (MyTrigger.Read, async (MyState _state, MyTrigger _trigger, CancellationToken _token) => {
        await Task.Yield ();
        Console.WriteLine ("call WhenFuncAsync callback");
        return MyState.Ready;
    })

    // 效果与 WhenFunc 一致,不过这函数指定异步方法
    .WhenFuncAsync (MyTrigger.FinishRead, async (MyState _state, MyTrigger _trigger, CancellationToken _token, string _param) => {
        await Task.Yield ();
        Console.WriteLine ($"call WhenFuncAsync callback with param [{_param}]");
        return MyState.Ready;
    })

    // 效果与 WhenAction 一致,不过这函数指定异步方法
    .WhenActionAsync (MyTrigger.Write, async (MyState _state, MyTrigger _trigger, CancellationToken _token) => {
        await Task.Yield ();
        Console.WriteLine ("call WhenActionAsync callback");
    })

    // 效果与 WhenAction 一致,不过这函数指定异步方法
    .WhenActionAsync (MyTrigger.FinishWrite, async (MyState _state, MyTrigger _trigger, CancellationToken _token, string _param) => {
        await Task.Yield ();
        Console.WriteLine ($"call WhenActionAsync callback with param [{_param}]");
    });

然后是触发一个事件:

// 异步触发一个事件,并传入指定参数
await _sm.TriggeringAsync (MyTrigger.Run, "hello");

// 限定异步任务最长执行时间,超时取消
var _source = new CancellationTokenSource (TimeSpan.FromSeconds (10));
await _sm.TriggeringAsync (MyTrigger.Run, _source.Token, "hello");

await异步触发的事件将在所有函数执行完毕之后返回。另外需要注意,同步与异步最好不要混用,使用的不好就很容易导致死锁,最佳实践是统一同步或统一异步。

results matching ""

    No results matching ""