2012-08-22 7 views
3

State Machine을 만들기 위해 Stateless Framework를 사용하고 있습니다. 내 메인 애플리케이션은 DataManager 클래스를 호출하는 ConsoleApplication이며, 은 Task을 시작하는 GetData 함수를 호출하고이 클래스는 상태 시스템과 함께 Receiver 함수를 실행합니다.Stateless Statement Framework 및 높은 CPU 사용률

내 문제는 StateMachine이 실행될 때 약 50 %의 CPU 사용률이 발생한다는 것입니다. 간단한 스위치 명령문과 동일한 작업으로 StateMachine을 구현할 때 0 % CPU 사용으로 실행됩니다! 코딩 오류가 있습니까? 아니면 Stateless Framework의 기습가입니까?

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

감사 마이클

답변

3

변경 대기 루프

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

루프없이 매우 효율적으로 수행하는 또 다른 방법입니다.

ManualResetEventSlim 개체를 만듭니다.

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

그리고 _machine.State가 될 때 State.End은 웨이터 신호되며 MRE 발생할

mre.Set(); 

를 호출 해

ManualResetEventSlim mre = new ManualResetEventSlim(false); 

대기 루프 변한다. 대기를 멈추기 위해 기다리십시오().

0

당신은 2 개의 코어를 가지고 있고 귀하의 스레드가 consumin이기 때문에 귀하의 CPU는 50 %입니다 g while 루프를 사용하면 100 %가됩니다.

switch 문에는 대기 루프가 없으므로 CPU를 소비하지 않습니다. 대신 수동 대기의

, 단지 Event-Based Asynchronous Pattern(EAP) 구현 : 무효가

  • 마크 수신기()를 따라서 문을 제거해야 돌아갑니다.
  • "OperationDone"과 같은 DataManager 클래스에서 이벤트를 선언하십시오.
  • steate machine의 마지막 단계에서 _outputList로 이벤트를 시작하십시오.
  • 이벤트를 캡처하여 값을 반환합니다.

이제 상태 시스템 프레임 워크 만 CPU 소비를 수행합니다.

또 다른 유용한 링크 : 방법 : Wrap EAP Patterns in a Task.