0

毎回バックグラウンドで集中的な作業を実行する1つのスレッドを持つ既存のアプリケーションがありますnumOfMinutesInterval。これは以前はThread.Sleep(インターバル期間全体にわたってスリープ)を使用して実行されていましたが、Thread.Sleepは悪であり、デザインがずさんであると読んだので、シグナリングメカニズムに変更したいと思います。以下は私が書いたばかりのコードです(wpfのディスパッチャータイマーを使用していますが、この小さなシナリオでは、winformsタイマーでも同じだと思います)。

ディスパッチャ(UIスレッドで実行)は毎秒ティックし、ティック関数内で間隔が経過したかどうかをチェックし、経過した場合は、manualreseteventを通知しSet()ます。集中的な作業がインターバル期間を超えて延長された場合、これは悪い設計ではないかと思いますか?を設定したが、作業に1分1秒かかった場合、作業がまだ行われていてワーカースレッドがまだブロックされていないときにティックがイベントを試行しているため、numOfMinutesInterval = 11回の呼び出しをスキップすることを意味します。set()set()

lastWorkDoneTime = DateTime.Now;呼び出し後に設定したことにも注意してください。Set()代わりにワーカースレッドに移動する必要がありますか(lastWorkDoneTime = DateTime.Now;直前に呼び出しmanualResetEvent.WaitOne();ます)?

これが悪いデザインの場合、それを変更するにはどうすればよいですか?読んでくれてありがとう!

//thread work done here
private void MyDoWork_ThreadStart() 
{
  while(FlagApplicationStillRunning == true)
  {
    //do the intensive work here
    manualResetEvent.WaitOne();
  }
}


// tick every second
private int numOfMinutesInterval = 1;
private DateTime lastWorkDoneTime = DateTime.Now;
private void DispatcherTimer_Tick(object sender, EventArgs e) 
{
  if((DateTime.Now - lastWorkDoneTime).Minutes > numOfMinutesInterval)
  {
    manualResetEvent.Set();
    lastWorkDoneTime = DateTime.Now;
  }
}
4

1 に答える 1

0

タスクを開始するだけで、集中的な作業を実行させることができます。

private void DispatcherTimer_Tick(object sender, EventArgs e) 
{
    if ((DateTime.Now - lastWorkDoneTime).Minutes > numOfMinutesInterval)
    {
        Task.Factory.StartNew(DoIntensiveWork());
        lastWorkDoneTime = DateTime.Now;
    }
}

を設定する限り、lastWorkDoneTimeそれはあなた次第です。タスクを起動するものに設定すると、2 つ以上のタスクが同時に実行されて作業が実行される可能性があります。作業を実行する関数の最後に設定すると、作業を完了するのにかかる時間に基づく遅延が発生します。

私は実際にタイマー オブジェクトの 1 つを使用して、DispatcherTimer_Tickイベントを使用する代わりにタイミングを処理できるようにします。System.Timers.Timer、 、 などがありSystem.Threading.Timersます。

どのタイマー オプションが最適かを判断する には、.NET Framework クラス ライブラリのタイマー クラスの比較を参照してください。

于 2013-02-21T00:42:45.777 に答える