use*_*611 4 python gtk multithreading
我正在使用 gtk3 创建 GUI。从而使图形用户界面和操作一起工作,我就与这个代码线程:threading.Thread(target=function).start()。没有线程,一切正常,但 GUI 将被冻结。使用线程,发生此错误:
第一个是 Segmentation fault (core dumped)
第二个是 *** glibc detected *** python: double free or corruption (!prev): 0x09154320 ***
第三个是 Gtk:ERROR:/build/buildd/gtk+3.0-3.4.2/./gtk/gtktextview.c:3726:gtk_text_view_va??lidate_onscreen: assertion failed: (priv->onscreen_validated) Aborted (core dumped)
你知道为什么会这样吗?
编辑: 我的代码:
图形用户界面
from gi.repository import Gtk, Gdk, GLib
import Process
import gobject
import threading
class gui():
def __init__(self):
self.window = Gtk.Window()
self.window.connect('delete-event', Gtk.main_quit)
self.box = Gtk.Box()
self.window.add(self.box)
self.label = Gtk.Label('idle')
self.box.pack_start(self.label, True, True, 0)
self.progressbar = Gtk.ProgressBar()
self.box.pack_start(self.progressbar, True, True, 0)
self.button = Gtk.Button(label='Start')
self.button.connect('clicked', self.on_button_clicked)
self.box.pack_start(self.button, True, True, 0)
self.window.show_all()
GLib.threads_init()
Gdk.threads_init()
Gdk.threads_enter()
Gtk.main()
Gdk.threads_leave()
def working1(self):
self.label.set_text('working1')
result = Process.heavyworks1()
print result
self.label.set_text('idle')
def on_button_clicked(self, widget):
threading.Thread(target=self.working1).start()
if __name__ == '__main__':
gui = gui()
Run Code Online (Sandbox Code Playgroud)
进程.py
a = 0 x = '东西'
def heavyworks1():
#global a
#doing something
#doing other thing
#a = something
#return result
def heavyworks2(param):
#doing something
#doing other thing
#return result
Run Code Online (Sandbox Code Playgroud)
我已经解决了这个问题。您需要做的是将任何 GTK 调用与任何线程完全分离。
发生这些错误是因为仍有一些代码从工作线程(在后台进行计算的线程)访问 gtk ui。我需要做的只是通过使用将所有gtk 调用从线程中分离出来gobject.idle_add(some_fuction_telling_gtk_what_to_do)
这是一个示例:
def stop_progress(self):
self.worker.join()
self.label.set_text('idle')
def working_thread(self, num):
self.textview.set_text(num)
Process.heavyworks2(num)
gobject.idle_add(self.stop_progress)
self.worker = threading.Thread(target=self.working_thread, args=[100000])
self.worker.start()
Run Code Online (Sandbox Code Playgroud)
您从该代码中看到一个假设在后台工作的函数 ( working_thread(self,num)) 仍然有一行访问 gtk 调用 ( self.textview.set_text(num))。将该代码分成一个函数,并使用gobject.idle_add(gtk_call_function).
变成了这个样子。
def stop_progress(self):
self.worker.join()
self.label.set_text('idle')
def updateTextView(self, num):
self.textview.set_text(num)
def working_thread(self, num):
gobject.idle_add(self.updateTextView, num)
Process.heavyworks2(num)
gobject.idle_add(self.stop_progress)
self.worker = threading.Thread(target=self.working_thread, args=[100000])
self.worker.start()
Run Code Online (Sandbox Code Playgroud)
所以,这里的一个重点是不要直接从任何线程更新 gtk ui。只需将访问 gtk 的每个代码分离成一个函数并gobject.idle_add()从线程调用它。
| 归档时间: |
|
| 查看次数: |
5807 次 |
| 最近记录: |