如何判断我们是不是在主线程中运行?

Posted

技术标签:

【中文标题】如何判断我们是不是在主线程中运行?【英文标题】:How to find out if we are running in main thread?如何判断我们是否在主线程中运行? 【发布时间】:2015-11-23 11:21:34 【问题描述】:

我们可以通过在main函数的开头调用std::this_thread::get_id()来获取主线程的id,比如this answer suggests。然后我们可以将这个id 存储在一个全局变量中,并与std::this_thread::get_id() 的调用进行比较。

但是,这迫使我们更改main 函数。有没有办法创建一个这样做的 library 函数?我正在考虑使用用std::this_thread::get_id() 表达式初始化的全局变量。由于全局变量(具有静态持续时间的变量)相对较早地初始化,因此不太可能(但并非不可能,请参阅:deferred dynamic initialization)在这些变量初始化之前产生线程。

我还可以使用一个辅助函数初始化全局变量,该函数枚举所有线程并选择创建时间最早的线程(基于this answer)。

我对多线程非常陌生,因此非常欢迎任何建议或指导。

【问题讨论】:

为什么?它对运行任何特定函数调用的线程有什么影响? 这样做的目的是什么?在您的代码中,您应该知道是否在主线程上调用了函数,就这么简单。 :) @DanielSanchez 有时它对完整性检查很有用,例如如果您正在设计一个通用库,例如​​,要知道哪个线程将调用一个函数,这并不总是那么容易。在这种情况下,库将与任何特定线程分离,并且它的函数可能会被任何线程调用。 在 Windows 中,进程可以比主线程寿命更长并产生更多线程。 blogs.msdn.com/b/oldnewthing/archive/2010/08/27/10054832.aspx 如果您的库在主线程终止后 由辅助线程加载怎么办? 如果您解释您正在尝试解决的实际问题,而不是寻求帮助实施您选择的解决方案,您将获得更好的答案。 【参考方案1】:

没有主线程这样的东西。有一个线程首先启动,但所有线程都是一等公民。通过修改链接器标志,我可以轻松创建一个程序,其中执行main() 的线程不会是首先启动的线程。

重新思考你的设计。

【讨论】:

我几乎同意。如果没有链接器标志,在 Windows 中,您可以在运行 WinMain 的线程中使用 ExitThread,而在 POSIX 中,您可以在运行 main 的线程中使用 pthread_exit。加载库时,第一个线程可能不再存在。然而,即使在两个系统中都有一个原始程序入口点,您也无法避免它在库加载和初始化之后运行 @PauloMadeira,加载和初始化库是一个很大的话题,尤其是延迟绑定:) 幸运的是,我在回答中没有提到这一点——我只是说线程正在执行main() 你是对的,你可以有一个在另一个线程中运行 mainWinMain 的原始入口点。 仅供参考,“主线程”(又名“UI 线程”)是 ios/macOS 上使用的术语。 @Jyaif 在问题中都看不到这些标签。【参考方案2】:

编辑

考虑到@ta.speot.is 和@David Schwartz 所说的,这不是获取主线程 ID 的可靠方法。

你可以在某处创建一个静态变量,用当前线程的 ID 进行初始化。

const std::thread::id MAIN_THREAD_ID = std::this_thread::get_id();

然后在其他地方:

if (std::this_thread::get_id() == MAIN_THREAD_ID)

    std::cout << "main thread\n";

else

    std::cout << "not main thread\n";

【讨论】:

谢谢。这是我考虑的第一件事,但是,问题是我不能保证MAIN_THREAD_ID 将在主线程中初始化。还是我??? 见this 所以是的,它应该在同一个线程上运行main 运行。 Hm 在 Windows 10 下的 Visual Studio 2015 中在普通控制台应用程序中为我工作。 这行不通。一方面,线程 ID 可以重复使用。 “一旦线程完成,std::thread::id 的值可能会被另一个线程重用。” 线程id不是只有在线程完成执行后才会重用吗?程序何时结束,OP没有提到应用程序生命周期之外的持久性。【参考方案3】:

如果您使用的是 MFC。您可以查看AfxGetMainWnd()。如果它返回一个 pWnd 那么你有(MFC)主线程。免责声明:如果您没有操作过m_pMainWnd 指针。

【讨论】:

以上是关于如何判断我们是不是在主线程中运行?的主要内容,如果未能解决你的问题,请参考以下文章

我们是不是需要在主线程或主队列中更新 UI?

[转]Android限制只能在主线程中进行UI访问的实现原理

GCD主队列是不是必须在主线程上执行?

C#如何禁用在主线程上运行的按钮?

如何在主线程上安全地使用[NSTask waitUntilExit]?

Glide