如何解决C#WPF线程如何正确停止
因此,在过去的几个月中,我一直在处理线程,并且尽管我的输出是预期的,但我仍然感觉自己并没有采取最佳方法。我似乎无法从任何与我合作的最佳实践中得到直接答案,所以我想我会问你们。 问题:我将尝试简化此过程,请耐心等待。说我有一个带有开始和停止按钮的表单。启动按钮将触发,并启动一个线程的事件。在该线程的“ 0”内部,将调用3个方法。 Method1()打印到控制台\“ A \\ n \” 10次,中间停顿10秒。 Method2()和Method3()完全相同,只是字母不同,且暂停时间在ѭ1之间。现在,当您按下停止按钮时,您希望立即做出响应。我不想等待方法完成。我该怎么办? 我一直在做的方式是将BackgroundWorker传递给每个方法并检查worker.CancellationPending像这样 public void Method1(BackgroundWorker worker)
{
for(int i = 0; i < 10 && !worker.CancellationPending; ++i)
{
Console.WriteLine(\"A\");
for(int j = 0; j < 100 && !worker.CancellationPending; ++i)
{
Thread.Sleep(100);
}
}
}
就像我说的那样,这给了我想要的结果,但是想像一下method1变得更加复杂,可以说它正在使用具有keydown和key up的DLL进行写入。如果我只是中止线程,那么我可能也会使自己处于不希望的状态。我发现自己的代码乱七八糟。实际上,每个代码块我都在检查CancellationPending。我在网上看到很多例子,很少见到有人像我一样绕过线程。最佳做法是什么?
解决方法
考虑使用迭代器(收益率回报)来分解步骤。
public void Method1(Backgroundworker worker)
{
foreach (var discard in Method1Steps)
{
if (worker.CancelationPending)
return;
}
}
private IEnumerable<object> Method1Steps()
{
for (int i = 0; i < 10; ++i)
{
yield return null;
Console.WriteLine(\"A\");
for (int j = 0; j < 100; ++i)
{
Thread.Sleep(100);
yield return null;
}
}
}
如果您有一堆try / catch / finally或一堆还需要了解取消的方法调用,则此解决方案可能难以实施。
, 是的,您做得正确。乍一看似乎很尴尬,但这确实是最好的选择。绝对比中止线程好得多。正如您所发现的,循环迭代是检查CancelationPending
的理想候选者。这是因为循环迭代通常会隔离逻辑工作单元,因此很容易划定安全点。安全点是线程执行过程中的标记,可以在不破坏任何数据的情况下轻松完成终止。
诀窍是经常在安全点轮询“ 5”,以便及时向呼叫者提供取消成功完成的反馈,但又不要过于频繁地对性能产生负面影响或“乱码”。
在您的特定情况下,内循环是轮询CancelationPending
的最佳位置。我将省略对外部循环的检查。原因是因为内部循环是大部分时间所花费的地方。对外部循环的检查将毫无意义,因为除了使内部循环继续进行之外,外部循环几乎没有实际工作。
现在,在GUI端,您可能希望将停止按钮显示为灰色,以使用户知道取消请求已被接受。您可以显示诸如“取消中止”之类的消息以使其清楚。一旦收到有关取消已完成的反馈,则可以删除该消息。
,好吧,如果您处于必须中止CPU密集型线程的情况,那么您就陷入了一个循环或另一个循环中测试\'Abort \'布尔值(或取消令牌)的麻烦(也许不是最里面的一个-取决于所需的时间)。 AFAIK,您可以从内部循环中“返回”,因此退出该方法-无需在每个级别进行检查!为了最大程度地减少这方面的开销,请尝试使其成为本地化的布尔值,即,尽量不要每次都通过六个......类来取消引用它。
Maybee从\'Stoppable \'继承类,该类具有\'Abort \'方法和\'Stop \'布尔值?您上面的示例线程花费了最多的睡眠时间,因此在进行任何检查之前,您将获得50ms的平均延迟。在这种情况下,您可以等待某些事件而超时而不是休眠。覆盖\'Abort \'来设置事件以及调用继承的Abort并因此尽早终止等待。如果要实现Dan所描述的新功能,也可以在cancelToken委托/回调中设置事件。
几乎没有Windows API等。它们很难\'不粘\\'或不具有异步\'Ex \'版本,因此它是错误的。\'nearly \'总是可以取消,一种或另一种方式,例如。关闭套接字以强制将套接字读取到除外,写入临时文件以强制返回文件夹更改通知。
Rgds,
马丁
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。