有很多函数应该从主线程调用。以我有限的经验来看,这些大多是 UI 功能。
示例:
- -[UIApplication delegate] must be called from main thread only )
- java.lang.IllegalStateException: Not on the main thread
- Drawing to window from child thread
假设我有一个 Fiber 库,可以使用设置/获取上下文创建“线程”。从主操作系统线程启动的任何纤程仅调用主线程函数是否安全?
我认为这很好,因为操作系统不知道我的光纤,但我不确定。我会对此进行测试,但结果不会是明确的,因为它可能有效,但依赖于未定义的行为。
编辑:将此问题标记为 C,因为 set/get context 是 C 函数,尽管正如评论中提到的,我认为它也可能适用于用其他语言编写的程序。
最佳答案
是的,您可以从任何上下文调用程序中的任何函数。请注意,使用 getcontext
和 setcontext
并不会创建真正的“线程”,并且您不会因此获得任何并行处理 - 您只是获得调度。这就是为什么它会起作用,无论它是否是 UI 函数。它基本上只是一个跨功能的 goto。引用manpage直接:
If the context was obtained by a call of getcontext(), program execution continues as if this call just returned.
这意味着如果我写
... 代码 ...
获取上下文(&cxt);
... 代码 ...
设置上下文(&cxt);
然后,当我到达 setcontext
时,我进入的状态与函数 getcontext
刚刚返回时相同。没有明显的差异(当然,您可能同时更改了内存值,但这不是重点)。联机帮助页与 makecontext
具有类似的保证,但请注意,它会在给定函数完成执行后重定向您。
您给出的示例是高级编程语言,其复杂性要高得多,因此不像C中的
。您发布的 Java 错误似乎实际上是一个不同的操作系统线程,与第三个示例相同。第一个示例看起来可能是一个假线程,但当然存在隐藏的复杂性,这可能会阻止 UI 调用工作(因为它们与外部 API 交互)。setcontext
/getcontext
那么简单
这就是为什么 JS 中的线程如此简单:因为线程不是真实的。您在并行性能方面所损失的东西,您却可以通过分派(dispatch)函数和 ajax 调用在任何地方调用任何内容。
如果您知道您的 Fiber 库实际上仅使用 getcontext
和 setcontext
,那么您就可以了。不过,该库可能会做其他事情,因此在这种情况下最好与库编写者进行验证。
关于从不同纤程调用需要主线程的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52797389/