2012-03-13 34 views
5

我正在编写一个必须在后台执行某些操作的应用程序:检查电子邮件并解析它们以在数据库中注入一些数据,并连接到Web服务以检查某些状态异步操作。检测低用户活动和检查背景上的电子邮件

现在,我的解决方案是一个简单的计时器,它按预定义的时间表执行这些操作:每五分钟发送一次电子邮件,Web服务每分钟检查一次(但这些只在有待处理活动时执行,所以大部分时间这没有什么。)

现在我没有使用线程(我在开发阶段早期)。但我的计划是创建一个后台线程,让它离线完成工作。

几个问题:

  1. 我计划,以控制定时器(S)的一切。设置一个全局变量(基本“锁定”)启动线程。如果“锁定”已设置,请忽略它。线程在终止时清理它。我应该为我的线程使用更强大的锁定/队列机制吗? (我已经安装了OmniThread)
  2. 如何运行低优先级的线程?当后台线程正在执行数据插入或联网时,我不希望应用程序感到呆滞。
  3. 是否有一种干净的方式来验证用户活动,并且只有当用户不忙于键盘/鼠标时才启动该线程?

请记住,我没有线程经验。我一次写了一个FTP同步应用程序,所以我不是一个完整的新手,但那是很久以前的事了。

+1

这是一个允许您创建/编辑发票等的应用程序,但它也需要阅读电子邮件并解析它以将所附电子发票作为收到的文档注入,并连接到税务办公室以获取已提交的发票状态。我不想中断用户的这些操作,所以我希望他们在后台运行。 – 2012-03-13 15:19:46

+1

如果您的后台工作与您的应用程序没有直接交互,我会建议您使用单独的服务(如果您愿意,可以将其设置为低优先级)来运行它们。所以,即使您的应用程序已关闭,甚至没有用户登录,也可以处理这些作品。 – Justmade 2012-03-13 15:28:34

+0

@Justmade - 当新电子邮件(发票)到达时,我确实希望收到一些通知。 – 2012-03-13 15:33:11

回答

1
  1. 我计划,以控制定时器(S)的一切。设置一个全局变量(基本“锁定”)启动线程。如果“锁定”已设置,请忽略它。线程在终止时清理它。我应该为我的线程使用更强大的锁定/队列机制吗? (我已经安装了OmniThread)

我根本不用打扰计时器。让你的线程循环看起来像这样,你会有拖延。你不需要锁,因为只有一个线程,直到前一个工作结束才会休眠。

procedure YourThread; 
var N: Integer; 
begin 
    while not Terminated do 
    begin 
    // Figure out if there's a job to do 
    // Do the job 

    // Sleep for a while, but give the thread a chance to notice 
    // it needs to terminate. 
    for N := 1 to 500 do 
     if not Terminated then 
     Sleep(100); 
    end; 
end; 
  1. 我怎么可以运行与低优先级的线程?当后台线程正在执行数据插入或联网时,我不希望应用程序感到呆滞。

不要打扰。你可以很容易地使用SetThreadPriority,但它是不值得的麻烦。如果你的后台线程正在等待I/O(网络),那么它将不会消耗任何CPU资源。即使您的后台线程全速运行,您的GUI也不会感觉迟缓,因为Windows在所有可用线程之间分配可用CPU时间方面做得很好。

  1. 有没有干净的方式来验证用户的活动,只有在用户不忙的键盘/鼠标启动这个线程?

再次,为什么要麻烦检查用户活动?检查电子邮件是网络(即:I/O)绑定,线程检查电子邮件将主要空闲。

+4

睡眠在一个线程50秒是有点超过顶部。请记住,当到了杀死线程的时候,应用程序将在最坏的情况下挂起50秒... – whosrdaddy 2012-03-13 18:44:33

+0

'请记住,当到了杀死线程的时候,应用程序将在最坏的情况下挂起50秒情况' - 如果操作系统在应用程序关闭时将其关闭,则不会。如果预计线程运行直到应用程序关闭,并且您没有明确地尝试终止并等待它们,则没有任何问题 - 应用程序将毫不迟延地关闭。 – 2012-03-14 12:02:41

+0

同意,但应用程序关闭后生活的线程是邪恶:) – whosrdaddy 2012-03-15 15:33:31

1

你能不能在后台线程中做所有这些,摆脱所有的线程微观管理?在我看来,你可以在后台线程中循环睡眠(60000)。每次循环检查Web服务,每5次检查一次电子邮件。如果需要,您可以将优先级设置为tpLower,但是几乎所有时间该线程都将在I/O上处于睡眠或阻塞状态,所以我认为它甚至不值得打字。

如果这样一个线程对键盘/鼠标的用户来说显而易见,无论它运行的时候,我都会感到惊讶。

'设置一个全局变量(基本的“锁定”,)启动线程' - 这个全局变量打算做什么?什么是锁定?

+0

我不知道这个线程需要多长时间才能完成。因此,如果TTimer设置为五分钟,则较早的调用可能仍处于活动状态;这就是为什么我提到某种形式的锁定。 – 2012-03-13 15:26:00

+0

由于只有一个后台线程,所以大部分时间都可以工作。所以你说这很便宜? – 2012-03-13 15:28:38

+0

@LeonardoHerrera - 应该没问题,是的。使用睡眠循环可使主线程“不在线” - 不需要定时器。如果一项活动需要超过五分钟时间,这并不重要 - 一项新活动要等到最后一项活动结束后五分钟才能开始。如果这个'jiter'是不可接受的,那么在上次活动运行开始时存储'lastRun'TdateTime并不难。然后可以在作为'trunc((now-lastRun)* msecPerDay)'的活动之后计算新的sleep()间隔。注意:如果这个数字是负数,不要睡在其他所有你会睡很久的时间! – 2012-03-13 16:31:18

6

对于您的问题的第3部分,Windows API有一个GetLastInputInfo函数,该函数应返回有关用户上次执行操作的信息。它甚至说它是 “这个功能对于输入空闲检测很有用”。我确实打算把它用于自己的东西,但没有机会去测试它。

编辑:Delphi implementation link

+0

它工作正常(用于调用屏幕保护程序,任务调度程序空闲任务等) – OnTheFly 2012-03-13 18:57:39