假设我有这样的代码:
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。您可以利用 CancellationTokenSource
和 CancellationToken
。您也可以考虑使用 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/