情况如下。我有一个线程,只需单击一个按钮即可开始。它然后工作大约2分钟(给予或采取相当多)然后完成,更新UI和一直。这很好。现在我决定在混音中添加一个“取消”按钮。我的问题是什么是从外部阻止线程的最佳方法?什么方法最好完全避免?我可以通过哪些资源了解自己,以获得有关该主题的更多知识。
另一条信息。该程序不是由我编写的,我只是“继承”它,现在我试图以小的方式扩展它的功能,使其更加用户友好。
编辑:使用VS2008和.NET 3.5
答案 0 :(得分:12)
事实上,如果你想安全地取消一些后台操作,最好的方法是创建私有布尔字段_isCancelled,它将在GUI线程和后台线程之间共享。如果用户按下取消,则只需将_isCancelled设置为false。并在后台线程中定期检查_isCancelled是否转为true并返回方法。
答案 1 :(得分:6)
阻止a的最佳方法是什么? 来自外面的线索?
线程必须合作。你需要一个共享标志(布尔值),并且线程代码必须定期检查它。
最好避免哪些方法 完全?
Thread.Abort的()。
答案 2 :(得分:5)
我经常在类似情况下使用System.ComponentModel.BackgroundWorker
。在UI端,调用其CancelAsync()
方法;在工作线程方面,定期检查CancellationPending
属性。
答案 3 :(得分:4)
在.NET中执行此类内容的一种“最佳”方法是使用BackgroundWorker。
BackgroundWorker将干净地处理进度更新(您目前只能运气,或通过大量繁琐的Invoke()调用),并提供干净的取消机制。
BackgroundWorker使用池线程而不是专用线程,这也是一种比其他线程更好的方法。
从外面停止一个线程几乎总是错误的做法,虽然从一开始它通常感觉就像你想要做的那样。
如果你使用的是.NET 4.0,那么还有一个全新的任务和取消机制,但是对我来说,对BackgroundWorker的研究对你来说是一个很好的第一点。
答案 4 :(得分:2)
你应该在工作线程偶尔检查的某个地方有一个标志。当标志表示线程应该取消时,它应该停止工作并正常退出。
答案 5 :(得分:2)
不是在UI和worker类之间寻找共享的布尔变量,而是使用重置事件(AutoResetEvents / ManualResetEvent)更清晰的方法。
但是,它仍取决于您在线程中执行的处理类型。 如果说是例如处理文件的循环,则可以使用重置事件线程构造。如果它是单个操作(例如复制一个巨大的文件),那么你无法取消它,而且你也不知道当前正在执行的线程。
如果您通过单击取消知道用户想要什么也会有所帮助 - 删除线程正在执行的所有操作或将应用程序带到以前的状态或完成当前正在处理的项目并立即返回。
答案 6 :(得分:1)
如果您使用的是.NET 4,请尝试Tasks and their built in cancelation mechanism。