【问题标题】:Design: Task B to pause Task A temporarily to take care of work, and then restart Task A设计:任务B暂时暂停任务A处理工作,然后重新启动任务A
【发布时间】:2014-11-23 17:13:01
【问题描述】:

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

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

伪代码:

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

然后这一切将永远持续下去(直到用户单击停止按钮并且程序结束)。

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

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

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

【问题讨论】:

  • 使用 Mutex、ManuallyResetEvent、Semaphore 等同步机制

标签: c# multithreading asynchronous task-parallel-library async-await


【解决方案1】:

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

【讨论】:

  • 谢谢大家。 Fejesjoco,这与@L.B 的建议相似吗?既然任务异步已经存在,这些类型的类/模式是否已经过时了?我有点困惑,因为有人曾经告诉我,很多原始线程现在已经过时了,所有新的任务异步功能都在那里......
  • 忘了问:1) 你会用任务而不是线程来做这些吗? 2)一旦用户单击停止按钮,您会使用取消令牌来取消线程/任务中的循环吗? (msdn.microsoft.com/en-us/library/dd997364.aspx)
  • 我不会将任务用于连续运行的作业,线程非常适合,但这只是一种意见。除非 .NET 类被正式废弃,否则在正确的情况下使用它并没有错。取消标记非常适合停止线程。
  • 知道了,非常感谢。我可以将任务标记为长时间运行以避免使用线程池,但我必须考虑常规互斥,因为我在真正学习老派线程之前直接跳到异步编程......
  • @fejesjoco:这将是一个很好的答案,值得一票,除了两个问题:您没有显示任何代码示例,以及对象引用应该是 @987654322 的声明@。就像问题应该包含代码示例一样,答案也应该包含(即使问题没有)。而锁定对象是否应该被static字段引用完全取决于使用它的代码是否为static(这里我们不知道)。
【解决方案2】:

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

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

不幸的是,.Net Framework 还没有内置实现 AsyncLockAsyncAutoResetEvent,但 Visual Studio SDK 有(或者您可以自己实现它们,like I did)。

【讨论】:

  • 感谢 l3arnon,一旦我成功实施了阻塞方法,我会调查这个问题。为了避免微调器(循环直到条件改变),我使用了 Timer。这是相当有效的。其他循环在每个循环中都起作用。
猜你喜欢
  • 2018-07-04
  • 2013-05-20
  • 2017-02-15
  • 2022-12-01
  • 2014-11-04
  • 2015-03-26
  • 2020-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多