2015-11-27 9 views
6

さまざまな答えは、スレッド内で眠ることは悪い考えであることを示唆しています(例:Avoid sleep)。なぜ正確に? 1つの理由は、スレッドがスリープしている場合にスレッドを正常に終了させるのが難しいことです(終了するように通知することによって)。スレッド内で寝る代わりに

たとえば、ネットワークフォルダ内の新しいファイルを定期的に確認する場合は、10秒に1回とします。これは、潜在的に時間のかかるファイルI/Oがメインスレッドに影響しないようにするため、優先度が低い(または最低の)スレッドには最適です。

代替手段はありますか?コードは、Delphiで与えられているが、任意のマルチスレッドアプリケーションにも同様に適用されます:

procedure TNetFilesThrd.Execute(); 
begin 
    try 
     while (not Terminated) do 
      begin 
      // Check for new files 
      // ... 

      // Rest a little before spinning around again 
      if (not Terminated) then 
       Sleep(TenSeconds); 
      end; 
    finally 
     // Terminated (or exception) so free all resources... 
    end; 
end; 

マイナーな変更は次のようになります。

// Rest a little before spinning around again 
nSleepCounter := 0; 
while (not Terminated) and (nSleepCounter < 500) do 
    begin 
    Sleep(TwentyMilliseconds); 
    Inc(nSleepCounter); 
    end; 

が、これはまだ睡眠を必要とする...

+1

マルチスレッドを使用すると、1つのスレッドでスリープ状態になると危険であり、未定義の動作につながる可能性があります。 – ITguy

+1

より良い方法は、同じタイムアウトの信号イベントを待つことです。イベントが通知された場合はすぐにスレッドを終了し、タイムアウトがあれば 'while'ループに留まります。 – kludg

+9

@ITguy Sleepingは本質的な危険性がなく、未定義の動作につながることはありません –

答えて

8

これを行う標準的な方法は、キャンセルイベントを待つことです。このように見える擬似コードで:イベントのいずれかがタイムアウトに

procedure TMyThread.TerminatedSet; 
begin 
    inherited; 
    FTerminationEvent.SetEvent; // abandon the wait in the thread method 
end; 

待ち、またはイベントが通知されるため、終了します。あなたを終了させるためには

while not Terminated do 
begin 
    // Check for new files 
    // ... 

    // Rest a little before spinning around again 
    FTerminationEvent.WaitFor(TenSeconds); 
end; 

TerminatedSetをオーバーライドします。これにより、スレッドはしばらくの間ポーズしてCPUに負担をかけずに、終了要求に応答したままになります。

+0

FTerminationEventのDelphi-7ユニット(またはD7相当品)が何であるか知っていますか?私は忙しいですが、それを見つけようとするグーグルではありますが、今はウサギの穴を下ろしています... – AlainD

+1

@AlainDあなたはスタンドアートTEventが必要です.FTerminationEventはこのイベントの意味を理解するための変数名です。 –

+0

@YuriyAfanasenkov:ああ、ありがとう!今すぐこの記事(http://stackoverflow.com/questions/1734644/how-to-start-stop-a-monitoring-delphi-thread-on-demand)を見つけて、それに続いています。それを試してすぐに報告します。 – AlainD

1

これが私の仕事だったら、10秒ごとに新しいスレッドを生成して、TTimerを含むラッパークラスで解決したと思います。

新しいスレッドの作成には多少コストがかかりますが、10秒ごとに行う場合は、メインスレッドのパフォーマンスが無視できる程度です。

ステップ:

  1. は、TMyFileSearcherをラッパークラスを作成します。
  2. TTimerが含まれているようにします。
  3. タイマーがヒットするたびに、新しいスレッドを生成してファイルを検索します。
  4. 返されたファイルを処理するために、TMyFileSearcherにOnTerminateハンドラを追加します。

古いスレッドが実行されている間に新しいスレッドを作成しないように、スレッドが生成されたかどうかを追跡するなど、他の考慮事項もあります。

しかし、これ以外にも実装するのはかなり簡単だと思います。

関連する問題