3

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

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

获取数据函数

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

数据管理器类

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

问候迈克尔

4

2 回答 2

4

更改等待循环

     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() 停止等待

于 2012-08-22T10:04:23.870 回答
0

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

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

无需手动等待,只需实现基于事件的异步模式(EAP)

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

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

另一个有用的链接:How to: Wrap EAP Patterns in a Task

于 2012-10-03T14:26:26.873 回答