替代睡在线程内
各种答案表明睡在线程中是一个坏主意,例如: 避免睡眠 。 为什么呢? 经常给出的一个原因是,如果正在hibernate,很难优雅地退出线程(通过发信号通知它终止)。
假设我想定期检查网络文件夹中的新文件,可能每10秒检查一次。 这对于优先级设置为低(或最低)的线程来说似乎是完美的,因为我不希望可能耗时的文件I / O影响我的主线程。
有哪些替代方案? 代码在Delphi中给出,但同样适用于任何multithreading应用程序:
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;
但这仍然涉及睡眠……
执行此操作的标准方法是等待取消事件。 在伪代码中,如下所示:
while not Terminated do begin // Check for new files // ... // Rest a little before spinning around again FTerminationEvent.WaitFor(TenSeconds); end;
要终止,您将覆盖TerminatedSet
:
procedure TMyThread.TerminatedSet; begin inherited; FTerminationEvent.SetEvent; // abandon the wait in the thread method end;
事件的等待时间超时,或因事件发出信号而终止。 这允许您的线程暂停一段时间而不会给CPU带来负担,同时还可以响应终止请求。
如果这是我的工作,我想我会用一个带有TTimer的包装类来解决它,每10秒生成一个新线程。
产生一个新线程有点代价,但如果它只是你每隔10秒做一次,那么主线程的性能可以忽略不计,我想。
脚步:
- 创建一个包装类,TMyFileSearcher。
- 让它包含一个TTimer。
- 每次定时器命中时,产生一个新线程并搜索文件。
- 向TMyFileSearcher添加OnTerminate处理程序,以处理返回的文件。
还有一些其他注意事项,例如跟踪是否已生成线程,以便在旧线程运行时不创建新线程。
但是,除此之外,我认为应该非常直接地实施。