You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gtkmm 4.10新FileDialog异步问题:调用函数提前退出

从gtkmm 4.8迁移到4.10:FileDialog异步回调的阻塞问题

我正从gtkmm 4.8迁移至4.10,想用新的FileDialog替代旧版FileChooserDialog。旧版FileChooserDialog可以设置为等待用户关闭对话框,但测试发现调用dialog->save()的函数不会等待回调处理完成,直接提前退出。

头文件代码

#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H

#include <gtkmm.h>

class ExampleWindow : public Gtk::Window
{
public:
  ExampleWindow();
  ~ExampleWindow() override;

protected:
  // Signal handlers:
  void on_button_file();
  void on_button_quit();
  void on_file_dialog_save(const Glib::RefPtr<Gio::AsyncResult> &result,
    const Glib::RefPtr<Gtk::FileDialog> &dialog);

  // Child widgets:
  Gtk::Box m_VBox;
  Gtk::Box m_ButtonBox;
  Gtk::Button m_Button_Quit;
  Gtk::Button m_Button_File;
};

#include "filedialog.h"

ExampleWindow::ExampleWindow()
: m_VBox(Gtk::Orientation::VERTICAL),
  m_Button_File("File"),
  m_Button_Quit("Quit")
{
  set_title("FileDialog example");
  set_default_size(100, 100);

  m_VBox.set_margin(5);
  set_child(m_VBox);

  m_VBox.append(m_ButtonBox);

  m_ButtonBox.append(m_Button_File);
  m_ButtonBox.append(m_Button_Quit);

  m_ButtonBox.set_margin(5);

  m_Button_File.signal_clicked().connect(
    sigc::mem_fun(*this, &ExampleWindow::on_button_file));

  m_Button_Quit.signal_clicked().connect(
    sigc::mem_fun(*this, &ExampleWindow::on_button_quit));
}
#endif //GTKMM_EXAMPLEWINDOW_H

CPP文件代码

#include "filedialog.h"

ExampleWindow::ExampleWindow()
: m_VBox(Gtk::Orientation::VERTICAL),
  m_Button_File("File"),
  m_Button_Quit("Quit")
{
  set_title("FileDialog example");
  set_default_size(100, 100);

  m_VBox.set_margin(5);
  set_child(m_VBox);

  m_VBox.append(m_ButtonBox);

  m_ButtonBox.append(m_Button_File);
  m_ButtonBox.append(m_Button_Quit);

  m_ButtonBox.set_margin(5);

  m_Button_File.signal_clicked().connect(
    sigc::mem_fun(*this, &ExampleWindow::on_button_file));

  m_Button_Quit.signal_clicked().connect(
    sigc::mem_fun(*this, &ExampleWindow::on_button_quit));
}

ExampleWindow::~ExampleWindow()
{
}

void ExampleWindow::on_button_file()
{
   auto dialog = Gtk::FileDialog::create();
   dialog->set_title("Testing file dialog save");
   printf("Created file/save dialog\n");
   dialog->save(*this,
     sigc::bind(
           sigc::mem_fun(
          *this,
          &ExampleWindow::on_file_dialog_save
          ),
           dialog
        )
      );
   printf("Exited file button handler\n");
}

void ExampleWindow::on_file_dialog_save(const Glib::RefPtr<Gio::AsyncResult> &result,
    const Glib::RefPtr<Gtk::FileDialog> &dialog)
{
   printf("Before save/finish call\n");
   auto file = dialog->save_finish(result);
   printf("After save/finish call\n");
}

void ExampleWindow::on_button_quit()
{
  set_visible(false);
}

程序运行输出

Created file/save dialog Exited file button handler Before save/finish call After save/finish call

可见文件按钮的处理函数提前退出,无法等待回调完成。我尝试添加信号量来阻塞等待:

修改后的文件按钮处理函数

void ExampleWindow::on_button_file()
{
   auto dialog = Gtk::FileDialog::create();
   dialog->set_title("Testing file dialog save");
   printf("Created file/save dialog\n");
   sem_wait(&m_dialog_semaphore);
   printf("Before dialog->save() call\n");
   dialog->save(*this,
     sigc::bind(
           sigc::mem_fun(
          *this,
          &ExampleWindow::on_file_dialog_save
          ),
           dialog
        )
      );
   sem_wait(&m_dialog_semaphore);
   printf("Exited file button handler\n");
}

修改后的回调函数

void ExampleWindow::on_file_dialog_save(const Glib::RefPtr<Gio::AsyncResult> &result,
    const Glib::RefPtr<Gtk::FileDialog> &dialog)
{
   printf("Before save/finish call\n");
   auto file = dialog->save_finish(result);
   printf("After save/finish call\n");
   sem_post(&m_dialog_semaphore);
}

但程序冻结,无法显示对话框,仅输出:

Created file/save dialog
Before dialog->save() call

看起来只有当文件按钮处理函数退出后,对话框才会显示。查看gtkmm示例代码过于简单,无法解决我的疑问,特此求助。

内容的提问来源于stack exchange,提问作者SRB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 22:37:31