У меня есть подкласс Gtk.Box, который содержит GLib.Timer, который запускает уведомление по истечении заданного интервала. У меня есть метод в этом классе, который вызывает this.destroy() в Gtk.Box. Таймер продолжает работать и запускает уведомление даже после уничтожения его родительского экземпляра. Все экземпляры этого класса, которые были уничтожены, демонстрируют это поведение и продолжают использовать процессор и память до тех пор, пока процесс не будет убит.уничтожение экземпляра класса не убивает экземпляры, которыми он владеет в vala
Как исправить это? Как я могу эффективно убивать экземпляры и как я могу вручную освобождать память вместо того, чтобы полагаться на сборку мусора vala.
редактировать: вот (стыдно) mvce
// mvce_deletable
// nine
// 2017.01.11
// valac --pkg gtk+-3.0 --pkg glib-2.0 deletablebox.vala
using Gtk;
using GLib;
class RemovableBox : Gtk.Box {
private Gtk.Button delete_button;
private GLib.Timer timer;
private Gtk.Label label;
public RemovableBox() {
delete_button = new Gtk.Button.with_label ("DESTROY");
delete_button.clicked.connect (()=>{this.destroy();});
this.add (delete_button);
label = new Gtk.Label ("0000000");
this.add (label);
timer = new GLib.Timer();
timer.start();
Timeout.add (50, update);
this.show_all();
}
private bool update() {
if (timer.elapsed() > 10.0f) {
stdout.printf("and yet it breathes\n");
}
label.set_text ("%f".printf(timer.elapsed()));
return true;
}
}
int main (string [] args) {
Gtk.init(ref args);
var window = new Gtk.Window();
window.destroy.connect (Gtk.main_quit);
var delete_me = new RemovableBox();
window.add (delete_me);
window.show_all();
Gtk.main();
return 0;
}
Я добавил timer_id в класс RemovableBox, но он по-прежнему не работает, как хотелось бы.
class RemovableBox : Gtk.Box {
private Gtk.Button delete_button;
private uint timeout_id;
private GLib.Timer timer;
private Gtk.Label label;
public RemovableBox() {
delete_button = new Gtk.Button.with_label ("DESTROY");
delete_button.clicked.connect (()=>{this.destroy();});
this.add (delete_button);
label = new Gtk.Label ("0000000");
this.add (label);
timer = new GLib.Timer();
timer.start();
timeout_id = Timeout.add (40, update);
this.show_all();
}
~ RemovableBox() {
Source.remove (timeout_id);
}
private bool update() {
if (timer.elapsed() > 10.0f) {
stdout.printf("and yet it breathes\n");
}
label.set_text ("%f".printf(timer.elapsed()));
return true;
}
}
Я даже не осознавал, что Вала делает RAII до сих пор. Являются ли классы не GObject также выделенными в стеке (например, на C++)? –
Статья Википедии относится к C++ и стек. Я думаю, что это немного вводит в заблуждение относительно общей концепции RAII. В Вале призывы освободить ресурсы создаются компилятором Vala в обратном порядке, к которому они были созданы. Таким образом, вы можете поднять «исключение» в блоке try, а деструкторы будут вызваны в обратном порядке, что позволит правильно освободить ресурсы. Это еще один вопрос, хотя :) – AlThomas
поэтому я объявил timer_id как uint и модифицировал класс, как вы сказали, но он по-прежнему не работает по желанию. – Nine