设计:任务 B 暂时暂停任务 A 以处理工作,然后重新启动任务 A

本文关键字:任务 处理 工作 然后 重新启动 暂停 设计 | 更新日期: 2023-09-27 18:31:32

我不知道如何以好的方式做到这一点。

基本上,我有一个程序,其中包含两个关键任务,其中包含循环,它一遍又一遍地运行,直到用户单击停止按钮。

伪代码:

  1. 任务 A 已启动:一个连续工作的 while 循环
  2. 任务 B 已启动:持续检查的System.Timers.Timer针对特定条件
  3. 如果任务 B 发现条件为 true,它应该暂时停止任务 A,并执行一堆工作
  4. 一旦任务 B 完成了这项工作,它应该允许任务 A 再次开始循环,并返回检查特定条件

然后,这一切都会永久持续(直到用户单击停止按钮并且程序结束)。

当我进行程序的第一次迭代时,我基本上创建了两个单独的线程,然后在我用于取消的循环中只有布尔值。因此,任务 B 只是将任务 A 中的布尔值设置为 false,并使用Thread.Join()等到任务 A 完全完成后再开始工作。任务 B 完成后,它再次在一个全新的线程上创建任务 A。这似乎效率很低,因为我没有理由真的必须结束线程,而我只想停止它,直到任务 B 完成。

我一直在通过任务并行库(async-await)阅读async操作,并认为我也许可以使用取消令牌而不是布尔值,但看起来一旦使用取消令牌取消任务,令牌就无法重置,任务无法重新启动。

无论如何,您将如何构建它?

设计:任务 B 暂时暂停任务 A 以处理工作,然后重新启动任务 A

创建用于锁定的对象。将任务 A 和 B 的工作部分放在此对象的 lock 语句中。确保锁定在线程 A 的循环内,以便让 B 有机会在迭代之间获取锁。这样,一次只能有一个线程进入锁定区域。线程 A 不必停止,它将在 B 完成后继续运行。(你也可以使用等待句柄,或互斥体,或者其他任何东西,这是相互排斥的最基本情况。

要以真正async-await的方式做到这一点,您不应该阻塞线程或让它们处于忙碌等待状态(不断循环,直到某些条件发生变化),因为它是同步的并且浪费资源。应使用async同步对象。

在您的情况下,您可以有一个AsyncLock来处理互斥部分(确保只有一个工作线程同时运行),并有一个AsyncAutoResetEvent来通知第二个工作线程条件更改。

不幸的是,.Net Framework还没有内置的AsyncLockAsyncAutoResetEvent实现,但是Visual Studio SDK有(或者你可以像我一样自己实现它们)。