在另一个线程中执行 Gtk.ListBox.insert 和 Gtk.ListBox.append 会导致 Vala 程



我正在用Vala编写一个使用Gtk.ListBox的程序。我有一个函数,它在其中使用 insert()。在某些时候(子级数量不同,但最终会发生),程序因分段错误而终止。这恰好发生在执行 insert() 函数时,我尝试添加一些 print() 函数来了解导致分段错误的原因。我也尝试用 append() 替换 insert()(我知道它们是不同的函数,我只是想检查程序是否会出现段错误),结果是一样的。

这是我正在使用的功能:

public new void prepend(MediaInfo post)
{
    Gtk.Separator separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL);
    base.insert (separator, (int) this.get_children().length () - 1);
    PostBox box = new PostBox(post);
    base.insert (box, (int) this.get_children().length () - 1);
    boxes.append(box);      
}

PostBox是从Gtk.EventBox继承的类,MediaInfo是我在程序中使用的类,它包含PostBox构造函数中使用的一些信息,boxPostBox对象列表)。

我在 for 循环中使用这个函数,所以它添加的不是一个框,而是许多框,并且在某些时候程序会出现段错误。

它似乎与我正在使用的 MediaInfo 类或 PostBox 类无关,因为有几次是在添加 Gtk.Separator 时发生的。

你能告诉我我的代码或其他东西有什么问题吗?我完全不知道如何处理它。

UPD:显然这与线程有关,因为我在我的程序中使用线程,并且在用函数调用替换所有创建的线程后,问题就消失了。

所有对 GDK 和 GTK+ 的调用都应从主线程进行。 通过使用 Vala 很容易做到这一点 GLib.Idle.add ,特别是如果您记住 Vala 支持闭包:

// Do stuff in your thread (CPU-intensive processing, I/O, etc.)
var value = blocking_operation ();
GLib.Idle.add (() => {
    // You can access local variables, like value, here.
    widget.set_something (value);
    // Returning false means the idle callback will be removed automatically
    // after it is called (instead of being called repeatedly).
    return false;
  });

基本上,您要做的是在其他线程中运行任务,当它们完成后切换回主线程(使用空闲回调)以修改 GTK+ 内容。

也就是说,我认为您可以安全地修改不属于GTK+正在绘制的任何层次结构的小部件。 因此,您可以在线程中实例化容器,添加一堆子项等,然后将其添加到主线程中的窗口中。 只是不要更改GTK+当前可能尝试绘制的任何内容。

最新更新