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
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
Your CPU is 50% because you have 2 cores in it and your thread is consuming the 100% of one it with the while loop.
The switch statement has no wait loop so it doesnt consumes CPU.
Instead of waiting manually, just implement the Event-Based Asynchronous Pattern(EAP) :
Now the only CPU consumption will be done by the state machine framework.
Another usefull link: How to: Wrap EAP Patterns in a Task .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.