3

Stateless Framework を使用して StateMachine を作成しています。私のメインアプリケーションは、クラスを呼び出す ConsoleApplication であり、DataManagerクラスを呼び出すGetData関数を呼び出して、ステートマシンで関数をTask実行します。Receiver

私の問題は、StateMachine の実行時に CPU 使用率が約 50% になることです。単純な 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;
}

よろしくマイケル

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には2つのコアがあり、スレッドはwhileループで1つのコアの100%を消費しているため、CPUは50%です。

switchステートメントには待機ループがないため、CPUを消費しません。

手動で待機する代わりに、イベントベースの非同期パターン(EAP)を実装するだけです。

  • Receiver()をvoidとしてマークし、returnステートメントを削除する必要があります。
  • 「OperationDone」のようなDataManagerクラスでイベントを宣言します。
  • スティートマシンの最後のステップで_outputListを使用してイベントを発生させます。
  • イベントをキャプチャして値を返します。

これで、CPUの消費はステートマシンフレームワークによってのみ行われます。

もう1つの便利なリンク:方法:タスクでEAPパターンをラップします。

于 2012-10-03T14:26:26.873 に答える