gpt4 book ai didi

python - 在 Python 线程中使用 Intvar/DoubleVar 是否安全?

转载 作者:行者123 更新时间:2023-11-28 22:48:14 25 4
gpt4 key购买 nike

让我先声明一下,我几乎毫无疑问会为我的程序使用一个Queue。我发布这个问题或多或少只是为了满足我的好奇心,因为我花了相当多的时间研究这个主题而没有找到任何结论性的答案。

那么,问题是:从主循环以外的任何地方访问/编辑 IntVar()DoubleVar() 等是否安全?另外,如果只是从一个单独的线程读取值(通过 x.get() )呢?我知道不应该从单独的线程编辑/更新小部件,但我没有找到有关 Intvars 等的信息。任何见解将不胜感激。

这是一个从未真正回答过的相关(但相当古老)的问题:

Python/Tkinter: Are Tkinter StringVar (IntVar, etc) thread safe?

最佳答案

基于 comments in the source code对于 _tkinter 模块,看起来 tkinter 实际上至少是 intended 线程安全的,只要 Tcl 是用 --enable-threads 构建的 选项。这得到了 Python 跟踪器 (issue11077) 上已解决的错误的支持,该错误指出 tkinter 不是线程安全的,最终确定 tkinter 的所有线程安全问题都是 Python 2.7.3 中修复的错误+

这是 _tkinter 模块的源代码对这个问题的看法:

The Tcl interpreter is only valid in the thread that created it, and all Tk activity must happen in this thread, also. That means that the mainloop must be invoked in the thread that created the interpreter. Invoking commands from other threads is possible; _tkinter will queue an event for the interpreter thread, which will then execute the command and pass back the result. If the main thread is not in the mainloop, and invoking commands causes an exception; if the main loop is running but not processing events, the command invocation will block.

因此,只要 mainloop 在应用程序的主线程中主动运行,tkinter 就会自动安排方法在主线程中运行,这将使其成为线程安全的。也就是说,除了实际的 Tkinter 源代码和上述错误报告之外,互联网上的大多数资源都表明将 tkinter 与线程一起使用会导致崩溃。我不太确定该相信什么,尽管在我尝试的一些小示例中,从线程更新 GUI 工作正常。

现在,您特别想知道与 Tk 小部件相关的线程安全规则是否也适用于 Variable 子类。确实如此:下面是 Variable 的一些实现,IntVar 的父级:

class Variable:

_default = ""
_tk = None
def __init__(self, master=None, value=None, name=None):
"""Construct a variable

MASTER can be given as master widget.
VALUE is an optional value (defaults to "")
NAME is an optional Tcl name (defaults to PY_VARnum).

If NAME matches an existing variable and VALUE is omitted
then the existing value is retained.
"""
# ...snip...
if not master:
master = _default_root
self._master = master
self._tk = master.tk

def set(self, value):
"""Set the variable to VALUE."""
return self._tk.globalsetvar(self._name, value)

当您设置一个变量时,它会在与Variable 关联的主控件上调用globalsetvar 方法。 _tk.globalsetvar 方法 is implemented in C ,并在内部调用 var_invoke,它在内部调用 WaitForMainLoop,它将尝试安排命令在主线程中执行,如 _tkinter< 中的引述所述 我在上面包含的源代码。

static PyObject*
var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
{
/* snip */

/* The current thread is not the interpreter thread. Marshal
the call to the interpreter thread, then wait for
completion. */
if (!WaitForMainloop(self))
return NULL;
/* snip */


static PyObject *
Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
{
return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
}

请注意,此代码路径也用于 get 操作,因此 setget 操作均受相同规则约束。

关于python - 在 Python 线程中使用 Intvar/DoubleVar 是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25351829/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com