【问题标题】:Stateless Statemachine Framework and high CPU usage无状态状态机框架和高 CPU 使用率
【发布时间】:2012-08-22 09:50:02
【问题描述】:

我正在使用无状态框架来创建状态机。 我的主应用程序是一个控制台应用程序,它调用DataManager 类,它 调用GetData 函数,该函数启动Task,然后使用状态机执行Receiver 函数。

我的问题是当 StateMachine 运行时我得到大约 50% 的 CPU 使用率! 当我使用简单的 switch 语句和相同的 Task 实现 StateMachine 时 它以 0% 的 CPU 使用率运行! 我有一些编码错误还是无状态框架的行为?

GetData 函数

public List<Byte[]> GetData()
{
    List<Byte> rawData = new List<Byte[]>();
    ReceiveTask = Task.Factory.StartNew<List<Byte[]>>(() => Receiver());
    //Wait until the Task is complete

    ReceiveTask.Wait();
    //return temp;
    rawData = ReceiveTask.Result;

    return rawData;
} 

DataManager 类

public partial class DataManager 
{

int _expectedBlocks;

Byte[] _currentMessage = null;
Byte[] _firstMessage = null;
int _currentBlockNumber = 0;

enum State { Idle, Start, Next, Check, End }
enum Trigger { DataOK, DataRequest, ReceivingFirstBlock, ReceivingNextBlock, LastPacketReceived, WaitForNext }

Dictionary<int, Byte[]> _receivedData;

List<Byte[]> _outputList;

StateMachine<State, Trigger> _machine;


private List<Byte[]> Receiver()
{
    _currentMode = Mode.Receive;
    m_source.MessageReceivedEvent +=new EventHandler<WSANMessageResponseEventArgs>(m_source_MessageReceivedEvent);
    m_source.StartConnection();
    _machine = new StateMachine<State, Trigger>(State.Idle);

    _receivedData = new Dictionary<int, byte[]>();

    _outputList = new List<byte[]>();

    //Config StateMachine
    _machine.Configure(State.Idle)
        .OnEntry(() => OnIdle())
        .OnExit(() => ExitIdle())
        .Permit(Trigger.ReceivingFirstBlock, State.Start);

    _machine.Configure(State.Start)
        .OnEntry(() => OnStart())
        .Permit(Trigger.ReceivingNextBlock, State.Next);

    _machine.Configure(State.Next)
        .OnEntry(() => OnNext())
        .Permit(Trigger.WaitForNext, State.Start)
        .Permit(Trigger.LastPacketReceived, State.Check);

    _machine.Configure(State.Check)
        .OnEntry(() => OnCheck())
        .Permit(Trigger.DataOK, State.End)
        .Permit(Trigger.DataRequest, State.Idle);

    _machine.Configure(State.End)
        .OnEntry(() => OnEnd());


     while (_machine.State != State.End)
     {

     }
    _currentMode = Mode.Idle;
    return _outputList;
}

问候 迈克尔

【问题讨论】:

    标签: c# .net state-machine stateless-state-machine


    【解决方案1】:

    更改等待循环

         while (_machine.State != State.End)
         {
             Thread.Sleep(10); // Only check once in a while
         }
    

    另一种无需循环即可非常有效地执行此操作的方法;

    创建一个 ManualResetEventSlim 对象;

     ManualResetEventSlim mre = new ManualResetEventSlim(false);
    

    等待循环变为

     mre.Wait(); // Waits untill the mre is signaled
    

    当 _machine.State 变成 State.End 它应该调用

     mre.Set();
    

    这将向服务员发出信号并导致 mre.Wait() 停止等待

    【讨论】:

      【解决方案2】:

      您的 CPU 是 50%,因为其中有 2 个内核,而您的线程正在使用 while 循环消耗 100% 的内核。

      switch 语句没有等待循环,因此不会消耗 CPU。

      不用手动等待,只需实现Event-Based Asynchronous Pattern(EAP)

      • 将 Receiver() 标记为 void,因此应删除 return 语句。
      • 在 DataManager 类上声明一个事件,例如“OperationDone”。
      • 在状态机的最后一步使用 _outputList 触发事件。
      • 捕获事件以返回值。

      现在唯一的 CPU 消耗将由状态机框架完成。

      另一个有用的链接:如何:Wrap EAP Patterns in a Task

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-12
        • 1970-01-01
        • 1970-01-01
        • 2010-11-27
        • 2012-01-18
        • 1970-01-01
        相关资源
        最近更新 更多