[英]How to end a endless looping background thread
专家们,
在 C# 中,我需要在主(GUI)线程旁边做一些无休止的循环工作。 因此,主线程创建循环线程,当主线程到达某个点时,它应该结束该循环。 这里我知道我的代码是错误的:
private bool m_MayRun;
private Thread m_Thread;
void mainthread() //e.g. the Form_Load event
{
...
m_Thread = new Thread(loopingThread);
m_Thread.Start();
...
m_MayRun = false; // e.g. later in the Form_Closing event
m_Thread.Join();
}
void loopingThread()
{
m_MayRun = true;
while(m_MayRun) // loop until m_MayRun is set to 'false' from the main thread
{
DoStuff();
}
}
明显的错误是使用变量“m_MayRun”有时会导致阻塞主线程,尤其是“加入”命令。 在 C++ 我会声明它是原子的,但我在 C# 中找不到这样的东西。 这个 m_MayRun 变量是唯一必须从主线程访问的变量,所以我正在寻找一种简单而美观的方法(没有很大的开销)来解决这个同步问题。 谢谢
像其他人建议的那样使用 volatile 关键字是一个好的开始。 volatile 关键字基本上告诉编译器该变量将从不同的线程访问,这将导致编译器减少/禁用所述变量的缓存。 线程可能在使用不同缓存的不同内核/处理器上运行,这些缓存存储不同版本的变量。
如果要确保线程不会同时访问变量,可以使用锁。 锁将导致您的线程等待,直到锁空闲。 通常,您在 class 中创建一个 object,该 object 仅用于该目的。 使用 locks 和 volatile 关键字,您的代码将如下所示:
private volatile bool m_MayRun;
private Thread m_Thread;
private readonly object _lock = new object();
void mainthread() //e.g. the Form_Load event
{
...
m_Thread = new Thread(loopingThread);
m_Thread.Start();
...
lock(_lock)
m_MayRun = false; // e.g. later in the Form_Closing event
m_Thread.Join();
}
void loopingThread()
{
lock(_lock)
m_MayRun = true;
while(true)
{
lock(_lock)
{
if(m_maxRun)
break;
}
DoStuff();
}
}
编辑:正如@Theodor Zoulias 指出的那样,您不必将 volatile 关键字与锁定一起使用。 实际上,在这种特定情况下,您可以使用 volatile OR 锁或互锁。 要了解每种方法的好处,您可能需要查看易失性与互锁与锁定
开销最低的方法可能是使用联锁class 中的方法。 更典型的 c# 方法是使用Cancellation token创建任务。 第三个选项是manualResetEvent(Slim) 。 在这种情况下,还有一个volatile关键字似乎应该解决同步问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.