因此,在过去的几个月里,我一直在研究线程,虽然我的输出符合预期,但我感觉我做这件事的方式不是最好的。我似乎无法从任何与我一起工作的人那里得到关于什么是最佳实践的直接答案,所以我想我会问问你们。
问题:我会尽量简化这个问题,请多多包涵。假设我有一个有开始和停止按钮的表单。启动按钮触发和启动线程的事件。在此线程的 DoWork
中,它将调用 3 个方法。 Method1() 向控制台打印 10 次“A\n”,中间暂停 10 秒。 Method2() 和 Method3() 完全相同,只是字母不同,Console.WriteLine
之间的暂停时间不同。现在,当您按下停止按钮时,您希望立即得到响应。我不想等待方法完成。我该怎么做?
我一直这样做的方式是将我的 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 变得更加复杂,假设它正在使用 DLL 来编写具有 keydown 和 key up 的代码。如果我只是中止线程,我可能也会让自己处于不希望的状态。我发现自己用 !worker.CancellationPending
弄乱了我的代码。实际上每个代码块我都在检查 CancellationPending。我在网上看了很多例子,但很少看到有人像我一样四处传递线索。这方面的最佳做法是什么?
最佳答案
考虑使用迭代器( yield 返回)分解步骤。
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 或一堆还需要了解取消的方法调用,则此解决方案可能更难实现。
关于C# WPF 线程如何正确停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6348393/