【发布时间】:2020-05-20 10:56:29
【问题描述】:
专家,
在 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 变量是唯一一个必须从主线程访问的变量,所以我正在寻找一种简单而美观的方法(没有很大的开销)来解决这个同步问题。谢谢
【问题讨论】:
-
如何将
CancellationToken传递给您的loopingThread方法,如果IsCancellationRequested为真,则检查每个循环,如果是,则从循环中检查break。现在您可以私下存储CancellationTokenSource并在需要时调用Cancel(ms docs on cancelling managed threads) -
我认为主线程有时会因为
thread.Join()方法和while loop DoStuff()内部执行的作业而被阻塞。你真的需要等到后台线程结束(例如,在它完成后你使用它的计算结果)吗?或者你只是想完成后台线程而不需要等到它完成? -
我想我不会在这里过度设计。只需将
m_MayRun设置为易失性,不要将其设置为trueinside 线程,但在开始之前。虽然不是特别有可能,但在主线程到达Join之前,线程实际上并没有启动。在这种情况下,您将拥有一个无限运行的线程和一个阻塞的事件队列。 -
你真的在循环中不停地
DoStuff吗?一个DoStuff和下一个之间没有延迟? -
@Iliar Turdeshev:我只需要以适当的方式取消 endles 循环即可进行清理。我知道“中止”命令,但这意味着我必须在线程中使用 try/catch/finally 构造,我不喜欢这有几个原因。
标签: c# multithreading synchronization