2

私は3つの別々のタイマーの間で絶えずジャグリングを開始するプログラムを持っています。

私のアプリケーションのメインスレッドには、グローバル変数がtrueに設定されているかどうかを常にチェックするwhileループがあり、設定されている場合は、1つのタイマーを停止し、他の2つのタイマーを起動します。 tは何らかの理由で停止するように命令されました。

このwhileループの条件は(1 == 1)であるため、永久に実行されます。

タスクマネージャー(XP)で、プログラムが多かれ少なかれアイドル状態のシステムでCPUの50%を使用していることがわかります。

whileループなどの速度を下げることでその数を減らす方法はありますか?

ありがとう。

4

7 に答える 7

11

whileループなどの速度を下げることでその数を減らす方法はありますか?

ビジーループをやめるだけです。スレッド間でイベントを調整するためのより良い方法があります。Monitor.Wait/ Pulse、またはAutoResetEvent/の使用を検討してくださいManualResetEvent。基本的に、グローバル変数を設定するスレッドは、それが行われたことを通知する必要があります。または、メインスレッドが他にもしない場合は、通常のC#イベントを追加して、変数が変更されるたびにイベントが発生し、適切なアクションを実行できるようにしませんか?

于 2012-04-09T08:49:52.647 に答える
6

プログラムはビジーウェイトを実行しますが、これは悪い習慣です。ループする代わりに、ある種の同期プリミティブ(待機ハンドルとも呼ばれます)をブロックするようにロジックを変更する必要があります。

待機ハンドルでのブロックはUIスレッドのオプションではないため、合計3つのスレッドを作成し、次のようなスキームを実装する必要があります。

  1. UIスレッドは、他のスレッドが何をするかにはまったく関係ありません。ループ、スリープ、ブロッキングはありません。
  2. 新しい「コントローラー」スレッドは、既存の「ワーカー」スレッドを開始し、すぐにブロックします(たとえば、通知されないイベントの場合)。イベントが通知されるまで(つまり、「ワーカー」が完了するまで)、CPUを消費することなく、この状態のままになります。
  3. 「ワーカー」スレッドはコースを実行してから、イベントを通知します。
于 2012-04-09T08:50:31.753 に答える
4

whileループなどの速度を下げることでその数を減らす方法はありますか?

はい、への呼び出しを挿入できますThread.Sleep(n)。粒度は約20ミリ秒です。

しかし、はるかに優れたオプションは、ウェイトハンドルを使用することです。
メインスレッドはハンドルを待機し、タイマーコードの終わりがそれをウェイクアップするように通知します。

于 2012-04-09T08:50:26.007 に答える
2

脅威を所定のミリ秒の間スリープさせる必要があります。Thread.sleep()関数を見て、whileループ内に配置します。

于 2012-04-09T08:50:01.177 に答える
2

このようなループを遅くする最も簡単な方法は、System.Threading.Thread.Sleep(100);を追加することです。反復ごとに、プロセスは100ミリ秒間スリープし、50%のCPUを使用しなくなります。

于 2012-04-09T08:50:19.747 に答える
2

タイマーの代わりにスレッドを使用すると、スレッドよりもコストがかかります。または、別のスレッドを開始する前に、停止した時間のスレッド状態を確認してください。コードロジックを削減することで、パフォーマンスを向上させることができます。

これがお役に立てば幸いです。:)

于 2012-04-09T08:51:35.673 に答える
0

ここでの答えは間違いではありませんが、while(true)ループを実行する際の多くの問題に実際には対処していませんwhile(1==1)

まず、アプリケーションが使用されている間ずっとループが実行されている場合でも、ユーザーがアプリケーションを終了するときなど、ある時点でループを停止する必要があります。これは、一定のループを持つスレッドがある場合、ユーザーがUIウィンドウを閉じると、プロセスはスレッドが終了するまで(これは、しばらくの間trueループになることはありません)、またはユーザーが賢くなり、タスクマネージャーから閉じるまで続きます。

ループの外側のアクセス可能なプロパティを参照するwhile条件チェックにtrue条件を設定することで、これを解決できます。

例:

private bool RequestExit = false;
private Thread MyLoopThread;
private void MyLoop()
{
  while (!RequestExit)
  {
    //Do stuff!
    Sleep(1);
  }
}
public void StartLoop()
{
  RequestExit = false;
  MyLoopThread = new Thread(MyLoop);
  MyLoopThread.Start();
}
public void StopLoop()
{
  RequestExit = true;
}

これは必要最低限​​のことであり、ダブルローンチやダブルシャットダウンイベントを回避することすらできません。

よりクリーンな方法は、プールする任意の間隔を10ミリ秒程度に設定することです。これは、ほとんどすべてのリアルタイムイベントで問題なく実行され、その間隔で起動するメソッドをトリガーします。

private Timer DoStuffTimer;
private void DoStuffMethod(object obj = null)
{
  //Do stuff!
}
public void StartLoop()
{
  DoStuffTimer = new Timer(DoStuffMethod,null,10,10);
}
public void StopLoop()
{
  DoStuffTimer.Dispose();
}
于 2015-03-24T20:00:15.263 に答える