繁体   English   中英

如何结束无限循环的后台线程

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM