如何完全"杀死"后台工作者?

54 c# backgroundworker

我正在编写一个Windows应用程序,它反复运行一系列数字IO操作.

当用户单击"开始"按钮时,此操作序列开始,并由后台工作人员在backgroundWorker1_DoWork()中完成.

但是,有时候我得到"这个背景工作者当前很忙......."的错误信息.

我正在考虑在代码中实现以下内容,通过使用while循环来"杀死"后台工作程序,然后再启动另一个操作序列:

if (backgroundWorker1.IsBusy == true)
{

    backgroundWorker1.CancelAsync();
    while (backgroundWorker1.IsBusy == true)
    {
        backgroundWorker1.CancelAsync();
    }

    backgroundWorker1.Dispose();

}

backgroundWorker1.RunWorkerAsync();
Run Code Online (Sandbox Code Playgroud)

我认为我主要担心的是,backgroundWorker1最终会被"杀死"吗?如果愿意,需要很长时间才能完成吗?

这种编码会让我陷入无限循环吗?

Ser*_*kov 76

你可以使用这样的东西(有关中止托管线程和ThreadAbortException的更多信息,请参阅Chris Sells的" 使用Rotor调整ThreadAbortException的深度 "):

public class AbortableBackgroundWorker : BackgroundWorker
{

    private Thread workerThread;

    protected override void OnDoWork(DoWorkEventArgs e)
    {
        workerThread = Thread.CurrentThread;
        try
        {
            base.OnDoWork(e);
        }
        catch (ThreadAbortException)
        {
            e.Cancel = true; //We must set Cancel property to true!
            Thread.ResetAbort(); //Prevents ThreadAbortException propagation
        }
    }


    public void Abort()
    {
        if (workerThread != null)
        {
            workerThread.Abort();
            workerThread = null;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

backgroundWorker1 = new AbortableBackgroundWorker();
//...
backgroundWorker1.RunWorkerAsync();

if (backgroundWorker1.IsBusy == true)
{
    backgroundWorker1.Abort();
    backgroundWorker1.Dispose();
}
Run Code Online (Sandbox Code Playgroud)

  • 顺便说一句,使用Thread.Abort杀死线程仍然很危险,因为并非.net框架中的每个类都在异步异常方面都很强大.但如果你知道你在做什么 - 没关系. (3认同)
  • 有几个提示:Thread.Abort在线程执行时不能中止线程:1)finally块,2)关键执行区域,3)非托管代​​码.这意味着如果您的代码执行第三方代码或其他代码,则无法预测此线程何时将被中止.请看一下Eric的帖子:http://blogs.msdn.com/b/ericlippert/archive/2010/02/22/should-i-specify-a-timeout.aspx (2认同)

pax*_*blo 18

我认为线程应该尽可能地负责自己资源,包括他们自己的生命.

从范围之外杀死线程通常是一个坏主意.设计用于将消息传递给线程以自行关闭的应用程序往往具有与多线程行为相关的问题少得多.

一个线程应监测所述消息,这可能是由另一个线程设置和读取由监视线程一个布尔值一样简单,及时和自行关闭干净,只要它可以.

这意味着它应该查找消息:

  • 在它的主循环中,如果有的话.
  • 定期在任何长时间运行的循环中.

用消息关闭它的线程应该等待(但当然不要停止GUI).

请注意,具有特定功能的线程环境还有其他可能性,例如线程可以随意标记自己可取消的情况,以允许外部查杀更安全.

但是,构建应用程序以留下自己命运的主线通常仍然更容易.

  • 如果线程访问可能阻塞该线程的外部资源,则杀死该线程可能是唯一的选择 (3认同)