更新:

再次感谢你的例子,它们对我很有帮助,我并不是说 夺走他们的一切。

Aren't the currently given examples, as far as I understand them & state-machines, only half of what we usually understand by a state-machine? In the sense that the examples do change state but that's only represented by changing the value of a variable (and allowing different value- changes in different states), while usually, a state machine should also change its behavior, and behavior not (only) in the sense of allowing different value changes for a variable depending on the state, but in the sense of allowing different methods to be executed for different states.

还是我对状态机及其常用用法有误解?


最初的问题:

我发现了关于c#中的状态机和迭代器块的讨论,以及用于创建状态机和c#的工具,所以我发现了很多抽象的东西,但作为一个新手,所有这些都有点令人困惑。

因此,如果有人能提供一个c#源代码-示例,实现一个简单的状态机,可能只有3,4个状态,那就太好了,只是为了了解它的要点。


当前回答

当我使用像RabbitMQ或Rabbit这样的消息代理时,我也很难使用状态机。

我制作这个视频是为了帮助别人。

https://www.youtube.com/watch?v=Vwfngk0YhLs&t=11s&ab_channel=GarryTaylor

代码来自这个Github回购

https://github.com/welhell/masstransit-saga-example

其他回答

我推荐state.cs。我个人使用state.js (JavaScript版本),并且非常满意。c#版本以类似的方式工作。

你实例化状态:

        // create the state machine
        var player = new StateMachine<State>( "player" );

        // create some states
        var initial = player.CreatePseudoState( "initial", PseudoStateKind.Initial );
        var operational = player.CreateCompositeState( "operational" );
        ...

你实例化了一些转换:

        var t0 = player.CreateTransition( initial, operational );
        player.CreateTransition( history, stopped );
        player.CreateTransition<String>( stopped, running, ( state, command ) => command.Equals( "play" ) );
        player.CreateTransition<String>( active, stopped, ( state, command ) => command.Equals( "stop" ) );

在状态和转场上定义动作:

    t0.Effect += DisengageHead;
    t0.Effect += StopMotor;

差不多就是这样了。更多信息请查看网站。

今天我将深入学习状态设计模式。 我做了并测试了ThreadState,它等于c#中的线程(+/-),如图所示

你可以很容易地添加新的状态,配置从一个状态移动到另一个状态是非常容易的,因为它封装在状态实现中

实现和使用at:实现。net ThreadState by State设计模式

下面是一个非常经典的有限状态机的例子,它模拟了一个非常简化的电子设备(比如电视)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace fsm
{
class Program
{
    static void Main(string[] args)
    {
        var fsm = new FiniteStateMachine();
        Console.WriteLine(fsm.State);
        fsm.ProcessEvent(FiniteStateMachine.Events.PlugIn);
        Console.WriteLine(fsm.State);
        fsm.ProcessEvent(FiniteStateMachine.Events.TurnOn);
        Console.WriteLine(fsm.State);
        fsm.ProcessEvent(FiniteStateMachine.Events.TurnOff);
        Console.WriteLine(fsm.State);
        fsm.ProcessEvent(FiniteStateMachine.Events.TurnOn);
        Console.WriteLine(fsm.State);
        fsm.ProcessEvent(FiniteStateMachine.Events.RemovePower);
        Console.WriteLine(fsm.State);
        Console.ReadKey();
    }

    class FiniteStateMachine
    {
        public enum States { Start, Standby, On };
        public States State { get; set; }

        public enum Events { PlugIn, TurnOn, TurnOff, RemovePower };

        private Action[,] fsm;

        public FiniteStateMachine()
        {
            this.fsm = new Action[3, 4] { 
                //PlugIn,       TurnOn,                 TurnOff,            RemovePower
                {this.PowerOn,  null,                   null,               null},              //start
                {null,          this.StandbyWhenOff,    null,               this.PowerOff},     //standby
                {null,          null,                   this.StandbyWhenOn, this.PowerOff} };   //on
        }
        public void ProcessEvent(Events theEvent)
        {
            this.fsm[(int)this.State, (int)theEvent].Invoke();
        }

        private void PowerOn() { this.State = States.Standby; }
        private void PowerOff() { this.State = States.Start; }
        private void StandbyWhenOn() { this.State = States.Standby; }
        private void StandbyWhenOff() { this.State = States.On; }
    }
}
}

您可以编写一个迭代器块,使您能够以编排的方式执行代码块。代码块是如何分解的并不一定要对应于任何东西,这只是你想要如何编码它。例如:

IEnumerable<int> CountToTen()
{
    System.Console.WriteLine("1");
    yield return 0;
    System.Console.WriteLine("2");
    System.Console.WriteLine("3");
    System.Console.WriteLine("4");
    yield return 0;
    System.Console.WriteLine("5");
    System.Console.WriteLine("6");
    System.Console.WriteLine("7");
    yield return 0;
    System.Console.WriteLine("8");
    yield return 0;
    System.Console.WriteLine("9");
    System.Console.WriteLine("10");
}

在本例中,当调用CountToTen时,还没有实际执行任何东西。您得到的实际上是一个状态机生成器,您可以为它创建一个状态机的新实例。可以通过调用GetEnumerator()来实现。生成的IEnumerator实际上是一个状态机,您可以通过调用MoveNext(…)来驱动它。

因此,在本例中,第一次调用MoveNext(…)时,您将看到“1”写入控制台,下一次调用MoveNext(…)时,您将看到2、3、4,然后是5、6、7、8,然后是9、10。正如您所看到的,这是一种编排事情应该如何发生的有用机制。

当我使用像RabbitMQ或Rabbit这样的消息代理时,我也很难使用状态机。

我制作这个视频是为了帮助别人。

https://www.youtube.com/watch?v=Vwfngk0YhLs&t=11s&ab_channel=GarryTaylor

代码来自这个Github回购

https://github.com/welhell/masstransit-saga-example