最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析C# 狀態(tài)機Stateless

 更新時間:2020年07月01日 08:36:16   作者:波多爾斯基  
這篇文章主要介紹了C# 狀態(tài)機Stateless的的相關資料,文中講解非常詳細,代碼幫助大家更好的理解和學習,感興趣的朋友可以了解下

最近在折騰一些控制相關的軟件設計,想起來狀態(tài)機這個東西,對解決一些控制系統(tǒng)狀態(tài)切換還是挺有用的。

狀態(tài)機(有限狀態(tài)自動機)網(wǎng)上有很多介紹。簡單理解就是定義一系列狀態(tài),通過一系列的事件,可以使得狀態(tài)可以相互之間切換。

如果不使用狀態(tài)機的思想來編程,那么針對過程的編程方法會使得程序拓展性變差,并且不容易調試。而狀態(tài)機只需要定義好了各種狀態(tài)和狀態(tài)切換之間的事件,你只管觸發(fā)事件,剩下的事情它自己就自動完成了(畢竟名稱叫做有限狀態(tài)自動機),這對于很多需要定義各種控制階段的系統(tǒng)簡直是完美適配。了解到.NET也有很多庫可以實現(xiàn)這些功能,本文主要介紹一下Stateless的應用。

Stateless介紹

Stateless可以創(chuàng)建極簡的狀態(tài)機與對應的工作流。很多項目(包括VisualStudio Extension、AIlab)都有使用到它。

它支持以下特性:

  • 支持各種類型作為狀態(tài)和觸發(fā)事件
  • 支持狀態(tài)繼承
  • 支持狀態(tài)進入/離開事件
  • 支持條件狀態(tài)轉移
  • 支持狀態(tài)/轉移查詢

也有幾點需要注意的:

  • 它支持異步語法,但是它是單線程的,不是線程安全的。
  • 可以導出DOT graph

安裝起來很簡單,直接在nuget中安裝即可:

Install-Package Stateless

Stateless使用

用起來也挺簡單的,以打電話這個事情為例,針對打電話的種種動作和狀態(tài)做成一個狀態(tài)機。
需要先定義一些狀態(tài)和事件/觸發(fā)器,電話有撥號、接通、留言等事件,有響鈴、掛起、掛斷等事件:

//代碼來自官方示例,可以在官方github庫上找到,略有修改以完整展示功能。
enum Trigger
{
  CallDialed,
  CallConnected,
  LeftMessage,
  PlacedOnHold,
  TakenOffHold,
  PhoneHurledAgainstWall,
  MuteMicrophone,
  UnmuteMicrophone,
  SetVolume
}

enum State
{
  OffHook,
  Ringing,
  Connected,
  OnHold,
  PhoneDestroyed
}

然后就是創(chuàng)建一個狀態(tài)機了:

_machine = new StateMachine<State, Trigger>(() => _state, s => _state = s);

最后也是最需要詳細解釋的,就是配置狀態(tài)機的行為了:

/*
為了解釋盡可能多的功能,以下程序修改了官方的代碼,可以在官方找可以直接執(zhí)行的代碼。
*/

//使用Permit指示發(fā)生某個事件后,從一個狀態(tài)變換到另外一個狀態(tài)。
_machine.Configure(State.OffHook)
  .Permit(Trigger.CallDialed, State.Ringing);

//設置一個帶參數(shù)的事件,這個事件是CallDialed的類型
var _setCalleeTrigger = _machine.SetTriggerParameters<string>(Trigger.CallDialed);
_machine.Configure(State.Ringing)
  //允許重新進入當前的狀態(tài),這個過程會觸發(fā)進入和退出動作
  .PermitReentry(Trigger.Ringing)
  //使用OnEntryFrom指示在觸發(fā)這個狀態(tài)的時候,運行某個動作,這里指定的是一個帶參數(shù)的事件
  .OnEntryFrom(_setCalleeTrigger, callee => OnDialed(callee), "Caller number to call")
  .Permit(Trigger.CallConnected, State.Connected);

_machine.Configure(State.OnHold)
  //定義子狀態(tài)
  .SubstateOf(State.Connected)
  .Permit(Trigger.TakenOffHold, State.Connected)
  .Permit(Trigger.PhoneHurledAgainstWall, State.PhoneDestroyed);

_machine.Configure(State.Connected)
  //進入狀態(tài)的時候執(zhí)行動作
  .OnEntry(t => StartCallTimer())
  //離開狀態(tài)執(zhí)行動作
  .OnExit(t => StopCallTimer())
  //狀態(tài)不變化,但是響應某種事件,和PermitReentry不同,它不會觸發(fā)進入和退出的動作
  .InternalTransition(Trigger.MuteMicrophone, t => OnMute())
  .InternalTransition(Trigger.UnmuteMicrophone, t => OnUnmute())
  .InternalTransition<int>(_setVolumeTrigger, (volume, t) => OnSetVolume(volume))
  .Permit(Trigger.LeftMessage, State.OffHook)
  .Permit(Trigger.PlacedOnHold, State.OnHold)
  //指定在發(fā)生同一種事件的時候,根據(jù)事件的參數(shù)不同而決定進入不同的狀態(tài)。
  .PermitIf(_setCalleeTrigger, State.Connected, callee => string.IsNullOrWhiteSpace(callee))
  .PermitIf(_setCalleeTrigger, State.Connected, callee => !string.IsNullOrWhiteSpace(callee))
  //如果沒有定義這個事件而發(fā)生了這個事件,會彈出異常。通過指定忽略某一類事件,可以避免這個情況。
  .Ignore(Trigger.CallDialled);

//當然也可以使用這個來避免彈出上面說的異常
_machine.OnUnhandledTrigger((state, trigger) => { });

//可以使用異步調用,但是必須要在觸發(fā)事件的時候,使用FireAsync
_machine.Configure(State.PhoneDestroyed)
  .OnEntryAsync(async () => await SendEmailToAssignee());

配置好了各狀態(tài)之間的轉換,下面就是觸發(fā)事件了。

public void Dialed(string callee)
{
  //有參數(shù)的觸發(fā)
  _machine.Fire(_setCalleeTrigger, callee);
}

public void Connected()
{
  //無參數(shù)的觸發(fā)
  _machine.Fire(Trigger.CallConnected);
}

public async Task PhoneDestroy()
{
  //異步觸發(fā)
  await _machine.FireAsync(Trigger.PhoneDestroyed);
}

public string ToDotGraph()
{
  //導出DOT GRAPH
  return UmlDotGraph.Format(_machine.GetInfo());
}

外部調用很簡潔:

phoneCall.Dialed("Prameela");
phoneCall.Connected();
phoneCall.SetVolume(2);
phoneCall.Hold();

只需要調用事件即可,別的都會按照我們設置好的動作來進行了,非常自動化。

總結

Stateless可以很好地實現(xiàn)狀態(tài)機,有點事件驅動的編程的感覺,但本質上不同,Stateless核心是各個狀態(tài)的遷移。

雖然Stateless很小巧方便,但是還有有很多地方不盡如人意(官方說這就是他們自己的設計目標,維持極簡):

  • 沒有啟動和停止的說法,一般在構造函數(shù)里面創(chuàng)建就一直有效。
  • 不是線程安全的
  • 拓展性有限

還有一個Appccelerate.StateMachine(地址),這個支持四種不同的狀態(tài)機實現(xiàn):

  • Passive State Machine: 同步單線程處理狀態(tài)轉換
  • Active State Machine: 同步多線程處理狀態(tài)轉換
  • Async Passive State Machine: 異步單線程處理狀態(tài)轉換
  • Async Active State Machine: 異步多線程處理狀態(tài)轉換

其中active的是線程安安全的。另外,它還支持狀態(tài)、事件的持久化,拓展性強。用法差不多,只是配置的關鍵字上面有一點區(qū)別,大家可以自行翻文檔。

以上就是淺析C# 狀態(tài)機Stateless的詳細內容,更多關于C# 狀態(tài)機Stateless的資料請關注腳本之家其它相關文章!

您可能感興趣的文章:

相關文章

  • 詳解c# 線程同步

    詳解c# 線程同步

    這篇文章主要介紹了c# 線程同步的相關資料,文中講解非常細致,示例代碼幫助大家更好的理解和學習c# 多線程,感興趣的朋友可以了解下
    2020-07-07
  • C#中comboBox實現(xiàn)三級聯(lián)動

    C#中comboBox實現(xiàn)三級聯(lián)動

    給大家分享了C#中comboBox實現(xiàn)三級聯(lián)動的全部代碼,代碼經(jīng)過測試,有興趣的朋友跟著做一下。
    2018-03-03
  • C#基于Spire.Doc for .NET從URL下載Word文檔的實現(xiàn)方案

    C#基于Spire.Doc for .NET從URL下載Word文檔的實現(xiàn)方案

    在日常的軟件開發(fā)中,我們經(jīng)常會遇到這樣的場景:需要從一個指定的 URL 地址下載文件,當涉及到 Word 文檔這類復雜的二進制格式時,情況就變得不那么簡單了,本文將深入探討在 C# 應用程序中,如何高效、可靠地從 URL 下載 Word 文檔,需要的朋友可以參考下
    2025-12-12
  • c#轉換全角半角方法示例

    c#轉換全角半角方法示例

    這篇文章主要介紹了c#如何轉換全角半角,大家可以看一下下面的代碼方法,可以參考一下
    2013-12-12
  • C#訪問SQLServer增刪改查代碼實例

    C#訪問SQLServer增刪改查代碼實例

    這篇文章主要為大家詳細介紹了C#訪問SQLServer增刪改查代碼實例,感興趣的小伙伴們可以參考一下
    2016-08-08
  • 深入理解C# abstract和virtual關鍵字

    深入理解C# abstract和virtual關鍵字

    深入理解C# abstract和virtual關鍵字,學習c#的朋友可以參考下。
    2011-06-06
  • C#使用PuppeteerSharp庫的示例代碼

    C#使用PuppeteerSharp庫的示例代碼

    PuppeteerSharp 是一個用于在 .NET 平臺上控制無頭(Headless) Chrome 瀏覽器的庫,本文主要為大家詳細介紹了C#中使用PuppeteerSharp庫的工具類,需要的可以了解下
    2023-12-12
  • C# SynchronizationContext以及Send和Post使用解讀

    C# SynchronizationContext以及Send和Post使用解讀

    這篇文章主要介紹了C# SynchronizationContext以及Send和Post使用解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • C#讀取或設置ScrollLock狀態(tài)的方法

    C#讀取或設置ScrollLock狀態(tài)的方法

    這篇文章主要介紹了C#讀取或設置ScrollLock狀態(tài)的方法,涉及C#操作ScrollLock滾動狀態(tài)的技巧,非常具有實用價值,需要的朋友可以參考下
    2015-04-04
  • winform 調用攝像頭掃碼識別二維碼的實現(xiàn)步驟

    winform 調用攝像頭掃碼識別二維碼的實現(xiàn)步驟

    這篇文章主要介紹了winform 調用攝像頭掃碼識別二維碼的實現(xiàn)步驟,幫助大家更好的理解和學習使用winform,感興趣的朋友可以了解下
    2021-02-02

最新評論

江都市| 南郑县| 塔城市| 万全县| 西华县| 恩平市| 青海省| 丰宁| 武威市| 崇文区| 襄汾县| 巴里| 黄冈市| 花莲市| 容城县| 宁城县| 兰坪| 水富县| 双流县| 石首市| 赤峰市| 深泽县| 樟树市| 康马县| 南宫市| 大足县| 古交市| 赣榆县| 清水河县| 内丘县| 石台县| 内乡县| 双鸭山市| 五家渠市| 桦甸市| 聂荣县| 清流县| 宣威市| 会同县| 深泽县| 含山县|