|
1
100
不幸的是,可能没有更好的选择。这取决于你的具体情况。我们的想法是把线优雅地停在安全的地方。这就是为什么
轮询停止标志
您已经提到了这个方法。这是很普通的一个。定期检查算法中安全点处的标志,并在收到信号时退出。标准方法是标记变量
在TPL中使用新的取消机制
这与轮询停止标志类似,只是它在TPL中使用了新的取消数据结构。它仍然基于合作取消模式。你需要一个
使用等待句柄
如果工作线程在正常操作期间需要等待特定的间隔或信号,则此方法非常有用。你可以
专用场景
有几种一次性方案具有非常专门的停止机制。把它们全部列举出来肯定是不在这个答案的范围之内的(不要介意这几乎是不可能的)。一个很好的例子就是
通过中断线程
这里的优点是它很简单,并且您不必将精力集中在用任何真正的东西来喷洒代码上。缺点是你对算法中的安全点几乎没有控制权。原因是因为
|
|
|
2
12
嗯,不幸的是,在多线程操作中,你经常不得不牺牲“快速性”来保证清洁…如果您
更新
即使它不是一个循环线程(也就是说,它可能是执行一些长时间运行的异步操作的线程,或者是执行某种类型的输入操作的块),您也可以
更新2是的,我有一个例子…我将根据您引用的链接向您展示一个示例:
|
|
|
3
8
如果取消是您正在构建的东西的一个需求,那么应该像对待其他代码一样尊重它——它可能是您必须为之设计的东西。 假设线程一直在做两件事之一。
如果您在所讨论的线程中受到CPU限制,那么 可能 找个好地方插入紧急援助支票。如果您调用其他人的代码来执行一些长时间运行的CPU绑定任务,那么您可能需要修复外部代码,将其移出进程(中止线程是邪恶的,但中止进程是定义良好且安全的)等。 如果您正在等待内核,那么等待中可能涉及到一个句柄(或者fd,或者mach端口,…)。通常,如果销毁相关的句柄,内核将立即返回一些失败代码。如果你在.NET/Java/等中,你很可能会遇到一个例外。在C语言中,无论您已经准备好处理系统调用失败的代码是什么,都会将错误传播到应用程序中有意义的部分。无论哪种方式,您都可以相当干净、非常及时地从低级的地方脱离出来,而不需要到处撒新的代码。 我经常对这种代码使用的策略是跟踪需要关闭的句柄列表,然后让我的abort函数设置一个“cancelled”标志,然后关闭它们。当函数失败时,它可以检查标志并报告由于取消而导致的失败,而不是由于特定的异常/errno。 您似乎在暗示可接受的取消粒度在服务调用级别。这可能不是一个好主意——您最好同步取消后台工作并从前台线程加入旧的后台线程。这是清洁的方法,因为:
害怕这种方法有两个原因:
|
|
|
4
2
也许问题的一点是您有这么长的方法/while循环。无论您是否有线程问题,都应该将其分解为较小的处理步骤。假设这些步骤是alpha()、bravo()、charlie()和delta()。 然后你可以这样做:
所以是的,它循环不断,但检查是否是时候在每个业务步骤之间停止。 |
|
|
5
2
你不必在到处都是水圈的时候洒水。外部while循环只是检查它是否被告知停止,如果停止,就不会进行另一次迭代… 如果你有一个直接的“去做一些事情并关闭”线程(其中没有循环),那么你只需要在线程中的每个主要点之前或之后检查“shouldstop”布尔值。这样你就知道它是应该继续下去还是应该退出。 例如:
|
|
|
6
2
最好的答案很大程度上取决于你在做什么。
<
> 过度工程?这取决于您使用多少状态机。如果你只有一个,是的。如果你有100个,那么也许没有。太狡猾了吗?嗯,要看情况。这种方法的另一个好处是,它允许您(稍作修改)将操作移动到timer.tick回调中,如果有意义的话,还可以完全取消线程。 做布卢茨说的一切。 |
|
|
7
2
不要在循环不属于的地方添加while循环,而是添加类似
|
|
8
1
没有很多方法可以让代码花费很长时间。循环是一个非常重要的编程结构。使代码长时间不循环需要 巨大的 报表金额。几十万。 或者调用其他为您执行循环的代码。是的,很难让代码按需停止。那不管用。 |
|
|
user107586 · 如何处理等待句柄不会导致无限循环? 1 年前 |
|
|
ron burgundy · 获取-释放语义是否跨线程传递?[副本] 1 年前 |
|
|
BenjiFB · C#内存缓存:在一次操作中追加到列表? 1 年前 |
|
|
András Takács · Python多线程问题 2 年前 |
|
|
András Takács · Python多线程错误 2 年前 |