【发布时间】:2013-11-05 14:36:48
【问题描述】:
我目前正在改进我们长期运行的方法,使其可以取消。我打算使用 System.Threading.Tasks.CancellationToken 来实现它。
我们的方法通常会执行一些长时间运行的步骤(主要是向硬件发送命令然后等待硬件),例如
void Run()
{
Step1();
Step2();
Step3();
}
我对取消的第一个(也许是愚蠢的)想法会将其转变为
bool Run(CancellationToken cancellationToken)
{
Step1(cancellationToken);
if (cancellationToken.IsCancellationRequested)
return false;
Step2(cancellationToken);
if (cancellationToken.IsCancellationRequested)
return false;
Step3(cancellationToken);
if (cancellationToken.IsCancellationRequested)
return false;
return true;
}
坦率地说,这看起来很可怕。这种“模式”也将在单个步骤中继续存在(而且它们已经相当长了)。这将使 Thread.Abort() 看起来相当性感,尽管我知道它不推荐。
是否有一种更简洁的模式来实现这一点,它不会隐藏大量样板代码下的应用程序逻辑?
编辑
作为步骤性质的示例,Run 方法可以读取
void Run()
{
GiantRobotor.MoveToBase();
Oven.ThrowBaguetteTowardsBase();
GiantRobotor.CatchBaguette();
// ...
}
我们正在控制需要同步才能协同工作的不同硬件单元。
【问题讨论】:
-
每个步骤是否完全独立于其他步骤?
-
你能把代码重构为有一个方法
Step(int number)吗?这样您就可以从 1 循环到 3 并检查取消令牌是否只请求一次? -
查看stackoverflow.com/questions/3632149/…,全面比较各种取消线程的方法。
-
你能在
Thread.Abort()调用和临界区之间使用互斥吗?然后,您只需要将关键代码互斥(可能会保存状态),然后让 Thread.Abort() 杀死其余代码。 -
这可能没有多大帮助,但值得一提:为它制作一个 Monad。我认为您可以在 C# 中实现一个。您的案例通常是 Monad 教程中的第一个示例(即当一个可能失败并且必须中止链时链接函数/步骤)。看向 Haskell 的
MaybeMonad 的方向。似乎是一个很好的概念契合。
标签: c# multithreading cancellation-token