Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stateless Statemachine Framework and high CPU usage

I'm using the Stateless Framework to create a StateMachine. My Main Application is a ConsoleApplication which calls the DataManager class, which calls the GetData function which starts a Task which then executes the Receiver function with the state machine.

My Problem is that I get about 50% CPU usage when the StateMachine runs! When I implement a StateMachine with a simple switch statement and the same Task it runs with a 0% CPU usage! Do I have a some coding error or is that the behaivor of the Stateless Framework?

The GetData function

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;
} 

The DataManager class

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;
}

Regards Michael

like image 957
user1616332 Avatar asked May 03 '26 15:05

user1616332


1 Answers

Change the wait loop

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

Another way to do this very efficiently without looping;

Create a ManualResetEventSlim object;

 ManualResetEventSlim mre = new ManualResetEventSlim(false);

The Wait loop changes to

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

And when the _machine.State becomes State.End it should call

 mre.Set();

which will signal the waiter and will cause the mre.Wait() to stop waiting

like image 129
IvoTops Avatar answered May 06 '26 04:05

IvoTops