c# - 使用标志退出 BackgroundWorker

标签 c# multithreading backgroundworker

假设我有这样的代码:

 private bool flag = false;
 public SomeClass()
 {
     public void setup()
    {
        worker = new BackgroundWorker();
        worker.DoWork += worker_DoWork;

        if(!worker.IsBusy)
            worker.RunWorkerAsync();
    }

    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        if(flag == true)
          return;
        //whatever You want the background thread to do...
        SomeClass.SomeStaticMethodWhichHasLoopInside();
    }
}

当用户在我的应用程序中单击“退出”按钮时,我可以在其中设置 flag=true - 这是停止由 BackgroundWorker 启动的线程的正确方法吗? 我只想在应用程序想要退出时这样做——这样我就可以停止线程。还是会被自动杀死?

最佳答案

没有。不要那样做。它不会按预期工作。您的 flag 字段甚至没有声明为 volatile;该字段的真实值可能尚未刷新到内存中。其他线程仍会将 flag 视为 false,因为它缓存了自己的值副本,而您的 BackgroundWorker 可能永远不会结束。

相反,只需调用 BackgroundWorker.CancelAsync并检查 BackgroundWorker.CancellationPending DoWork 事件处理程序中的 bool 值。

private void OnExit(..)
{
    worker.CancelAsync();
}

所以你的 DoWork 方法将变成

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    while(!worker.CancellationPending)
    {
        //whatever You want the background thread to do...
    }
}

如果没有循环,则需要不时检查CancellationPending属性。

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    if(worker.CancellationPending)
        return;
    //Do something..
    if(worker.CancellationPending)
        return;
    //Do some other thing..
    if(worker.CancellationPending)
        return;
    //Do something else..
}

I want to do this only when application wants to quit - so that I stop the thread. Or it will be automatically killed?

由于该线程是后台线程,它会被 CLR 自动终止。但是,不要依赖这个事实,因为我们不知道在 CLR 终止线程时您的线程将执行什么。例如,它可能一直在写入一个文件,在这种情况下,您会留下损坏的文件。

后果可能更糟,因此始终建议您自己优雅地停止线程。

Question asked in comments: How can I cancel when the loop is in some other method?

看来您使用的是 .Net4.5。您可以利用 CancellationTokenSourceCancellationToken。您也可以考虑使用 TPL 和异步等待功能,这将使您的生活更轻松。

private CancellationTokenSource tokenSource = new CancellationTokenSource();

private void OnExit(..)
{
    tokenSource.Cancel();
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    //whatever You want the background thread to do...
    SomeClass.SomeStaticMethodWhichHasLoopInside(tokenSource.Token);
}

class SomeClass
{
    public static void SomeStaticMethodWhichHasLoopInside(CancellationToken token)
    {
        while (!token.IsCancellationRequested)
        {
            //Do something
        }
    }
}

关于c# - 使用标志退出 BackgroundWorker,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30231189/

相关文章:

C#套接字接收线程

c# - C++ char* 和 C# 字节

java - 将实际命令作为参数传递 Java

java - 为什么访问规则不适用于非根组?

java - 两个线程共享静态 boolean 字段,但第一个线程仍然不退出

ruby-on-rails - delayed_job、守护进程或其他用于重复后台作业的 gem

c# - ListBox 中的多个条目合并

c# - BackgroundWorker 问题(C# Windows 窗体)

C#后台 worker ,winform。 "Cross-thread operation not valid:"

c# - 我可以在 C# 项目上使用 .rc 资源文件吗?