【问题标题】:Limiting number of threads run from timer限制从计时器运行的线程数
【发布时间】:2016-04-25 12:40:17
【问题描述】:

我有一个WM_TIMER 回调函数每 50 毫秒触发一次,在此我创建一个线程只是为了确保 ui 线程不阻塞,这些线程在共享内存上运行,我使用 mutex 使线程安全 对象。

我的问题是,当创建新线程并且较早的线程尚未完成时,它们在到达WaitForSingleObject(ghMutex, INFINITE) 行后进入等待状态,因为内存中的活动线程数将呈指数增长,可能我应该在没有计时器的情况下这样做,但我认为使用计时器可以更好地管理频率。

我还尝试使用线程计数器(告诉活动线程的数量)并在计数器大于零时从回调函数返回,据我了解这不是线程安全的。

我应该怎么做才能让一个线程随时运行,例如,如果一个线程未能获得互斥锁,那么它应该终止而不是等待。

【问题讨论】:

  • 你可以用单线程来做,没有 WM_TIMER。你的线程会有一个主循环,在顶部它会使用 GetCurrentTime() 记住开始时间,然后去执行它的任务。执行后检查是否应该 ::Sleep() 这个线程的剩余时间(直到 50 毫秒),或者继续循环。但是你不会同时执行多个线程,所以我不确定这是否是你想要的。
  • @MarcinJędrzejewski 是的,我不需要在任何时候执行多个线程,顺便说一句,性能如何,因为这里我有几个 GetCurrentTime() 和一个 IF 语句。
  • 你肯定做错了。单线程是你需要的。大概。我们不知道您的实际问题。
  • @David 我会走这条路
  • 如果您的解决方案涉及每 50 毫秒生成一个新线程,那么就大错特错了。希望使用计时器控制频率也不会奏效:计时器是低优先级的,只有在队列中没有任何更高优先级的消息时才会触发。你真的需要重新审视你的设计。至于问题:不知道你的最终目标是什么,它并不是真的有用。

标签: c++ winapi


【解决方案1】:

根据您的描述和其他 cmets,您可以执行以下操作:

有:

  • GUI 的一个线程(接收定时器事件)
  • 处理的另一个线程。
  • 一个事件(使用CreateEvent 创建)

处理线程将有一个很大的无限for(;;) 循环,从等待事件开始,然后执行所需的处理。计时器事件不是每 50 毫秒触发一个新线程,而是调用SetEvent 来触发处理线程。

这样,您不能同时拥有多个“处理器”。如果处理时间超过 50 毫秒,则将其丢弃。

如果每个事件需要超过 50 毫秒的时间才能进行,您可以拥有多个处理线程+事件,并且您可以从计时器以循环方式交替触发它们(通过它们循环)。

【讨论】:

  • 看起来像一个干净的解决方案,你是说setevent如果不处理就不会堆积和丢弃吗?
  • 是的,在内部,它是一个布尔值(有信号/无信号)。如果不清除事件,对同一对象的多个 SetEvent 将不起作用。
【解决方案2】:

在我看来,您违反了线程最基本的原则之一(尽管@Dim 的回答是一种改进,但它仍然在做同样的事情)。要记住的最重要的一点是线程应该尽可能独立地运行。理想情况下,您希望将线程之间的同步和通信降至最低,使其完成工作。

在这种情况下,最小值似乎是“无”。主线程必须创建工作线程。在那之后,您所描述的一切都不需要任何进一步的沟通。

至少据我了解,这里的意图是工作线程以 50 毫秒的间隔进行某种处理。假设这是正确的,您似乎完全没有从涉及 UI 线程中获得任何好处。相反,您应该启动一个(并且只有一个)工作线程,并在循环中执行以下操作:

  1. 记录当前时间
  2. 进行处理
  3. 自启动后剩余 50 毫秒的睡眠时间(如有必要)
  4. 重复

虽然您没有对此进行任何描述,但我认为(可能)需要线程间通信的唯一地方是该工作线程告诉 UI 线程一轮处理已完成,并且UI 可以使用数据来更新 UI。我不知道在您的情况下采用什么形式(并且它可能根本没有必要)但我至少可以看到它可能需要的地方。然而,仅仅让线程每 50 毫秒执行一次操作并不足以证明进行任何类型的线程间通信(更不用说每 50 毫秒创建一个新线程的开销,然后增加更多开销以确保您一次只有一个工作线程)。

【讨论】:

  • 我真的不需要来回通信,因为线程直接更新主线程使用的变量,顺便说一句,我们应该相信线程间通信,可能有些事件可以跳过?
  • 不是“有些事件可以跳过”的问题。很简单,一个事件只有两种状态:设置和清除。如果您设置了一个已经设置好的信号,它只会保持设置状态。它就像 bool 变量一样工作——如果它已经是 true 并且您将 true 分配给它,那不会改变任何东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-13
  • 2019-07-14
  • 1970-01-01
  • 2011-12-26
  • 2012-02-17
  • 1970-01-01
  • 2016-01-05
相关资源
最近更新 更多