2009-06-06 145 views
6

私のアプリケーションにはバックグラウンドで動作するスレッドがいくつかあります。データベースに接続し、時間のかかる選択クエリを実行します。ほとんどの場合、これらのクエリは複数のレコードしか返しません。しかし時々、数万レコードを返すことがあります。これらはすべてループで処理されます。Delphi - スレッドのスリープ時間を調整する

このような状況は、同時に複数のスレッドで発生する可能性がありますので、私はそれらのスレッドがデータを処理しているとき、私のアプリケーションがCPU時間の100%を使用したくありません。私はすべてのスレッドをプロセッサの時間の間に戦わせたくありません。したがって、これらのスレッド内のループの各反復でSleep()関数を呼び出します。

ただし、スリープ時間の調整方法はわかりません。私はループが永遠に続くことを望んでいないので、睡眠期間が長すぎることはできません。私は2ミリ秒ごとに(各スレッドで)(なぜ2ms? - これは良い質問です:))を設定します。

は、私は睡眠時間を延長、一度だけ、すべてのn回の反復を(、のは言うスリープ(100)ごとに50回の反復を聞かせて)、睡眠を呼び出すことができることを、他方では、と思いました。どのアプローチを選ぶべきですか?ループの1回の反復には、それぞれ約30ms(スリープなし)が必要です。

お知らせください。

ありがとうございます!
マリウス。

答えて

9

スリープ()を呼び出すは意味がありません。取得できるすべての処理能力を使用して、スレッドの最適なスケジューリング方法をシステムに教えるようにします。 Sleep()を呼び出すと、余分なコンテキストスイッチが発生し、スループットが低下します。バックグラウンド処理がメインスレッドまたは他のアプリケーションと干渉する場合は、それに応じてバックグラウンドスレッドの優先度を下げます。

あなたはスレッドが、彼らは消費者のために生成されるデータの量を制限するために眠るようにしたい場合は、生産者 - 消費者 - キューに見えます。プロデューサスレッドはキューがいっぱいになったときにブロックするだけです。このようにして、タイミングを練るために何もする必要はありません。

また、特に最新のプロセッサでは、最大CPUを使用するのが一般的には良いことです。プロセッサー/システム全体がより早く低電力状態に入ることができるように、高負荷の短時間のラップトップであっても、あなたのタスクが必要とする時間を人工的に延長するよりも優れています。

+0

を使用しかし、これはまた、誰かが作業しているコンピュータ(たとえば、スプレッドシートを書くこと)にバックグラウンドで実行された場合、あなたはしないでくださいバックグラウンドプロセスでフォアグラウンドプロセスを使用できないようにしたい。 – dummzeuch

+2

真実ですが、そのため、バックグラウンドスレッドの優先度を下げて、他のアプリケーション(またはメインスレッド)を応答可能に保ちながら、システム全体の潜在能力を利用できるようにしています。現代(マルチコア)システムでは、すべてのコアを十分にロードしておくことは、フォアグラウンドアプリケーションの応答性の欠如よりもはるかに大きな問題です。とにかく、大量の最適化されていないI/Oは、システムのユーザビリティに対する大きな脅威です。 – mghie

2

スレッドを制御するためにスリープを使用するよりも良い方法があります。データベースの呼び出しで1〜1000秒のレコードが返されるため、アプリケーションを2つのレイヤーに分けることができます。メッセージキューを使用して要求をバッファすることもできます。あなたのアプリケーションはデータサービスを呼び出すことができ、データサービスはクエリを実行し、個々のデータメッセージ(またはメッセージブロックなど)をキューに送ります。あなたのアプリはメッセージを処理するのに適切な数のスレッドを作成できます。スレッド数が増えるとCPUを犠牲にして処理が高速化されますが、これを調整して適切なバランスを取ることができます。

3

方が良いだけの低優先度のスレッドを作成し、それらがそうでなければ、CPUのフルパワーを使用していない、寝ずに仕事しましょう。例えば、マルチコア/マルチCPUシステム上。または、システムが100%アイドル状態の場合:なぜ待つか、眠るのですか?

しかし、あなたはしかし、いくつかのスリープが必要な場合は、その睡眠に注意してください(1)ので、Windowsのデフォルトのタイムスライスの10-15msを(!)を待ちます。 MMSystem.pasユニットのtimeBeginPeriod(1)を使用して解像度を1msに設定することができます:-)(私はこれをシリアル通信に使用しました)。

0

WinApiのSleep()ではなく、System.ClassesのTThread.Sleep()を使用します。Windowsの

// Winapi.Windows contains GetTickCount and Sleep 
// System.Classes contains TThread (universal option) // TThread.GetTickCount() // TThread.Sleep() 
uses System.Types, System.Classes, Vcl.Forms; 

//その後、あなたのプロセスでは、次の

TThread.Sleep(0); 

Application.ProcessMessages(); // clear all Vcl messages // part of Vcl.Forms 
CheckSynchronize(); // check all threaded events 
関連する問題