我正在尝试编写一个使用C ++ 11多线程的gtkmm应用程序。但是,我一直遇到Fatal IO error 11 (Resource temporarily unavailable) on X server
错误。
我的窗口上有几个Gtk::Image
个对象。每个人都有自己的Gtk::EventBox
,我必须定期更改图片。为此,我创建了一个包含特定块的事件框的类,它有一个删除前一个图像的函数,生成新图像并将其放在那里。
这是一段代码:
while (lock_flag.test_and_set()) {} // std::atomic_flag lock
// ...
std::cerr << 1;
eventBox->foreach(
[eb = this->eventBox](Gtk::Widget& w)
{
eb->Gtk::Container::remove(w);
}
);
std::cerr << 2;
eventBox->add(*im);
std::cerr << 3;
eventBox->show_all_children();
std::cerr << 4;
// ...
lock_flag.clear();
当error 11
出现时,某些数字不会打印到std::cerr
,但问题发生的地方每次都不同(我最近观察到它在12之后和123之后崩溃)。因此,我得出的结论是,在某处使用的资源不是图像,而是eventBox
。但是在程序初始化之后,它不会在此函数之外的任何地方访问,并且此函数包含std::atomic_flag
锁。
问题:这种行为可能是什么原因?我可以确保它不会发生吗?或者我能抓住这个错误并期望从中恢复吗?
编辑:
我试过了
std::thread
更改为Glib::Threads::Thread
,但无济于事,仍然遇到同样的错误。GDK_SYNCHRONIZE
添加到环境中,这会产生[xcb] Unknown request in queue while dequeuing/[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
错误。这导致我this post,之后我尝试在开始新主题之前调用XInitThreads()
(通过Glib::Threads::Thread
和std::thread
),但这没有任何积极意义;除了曾经有一些侥幸,线程实际上已经执行了整个功能(在屏幕上显示&#39; 4&#39;)但是仍然设法使用相同的error 11
消息而死亡。答案 0 :(得分:2)
最后,我是如何解决所有问题的。
通过Phillip提供的链接,我发现了Glib::signal_timeout()
,这使我能够在我的代码中完全重新考虑并行性的概念。
以下是我必须要做的事情:
if(running) return;
running = true;
static bool firstTime = true;
if(firstTime)
{
XInitThreads();
firstTime=false;
}
std::function<void()> f = [this] () -> void
{
while(running)
{
this->takeStep();
std::this_thread::sleep_for(std::chrono::milliseconds(300));
}
};
std::thread(f).detach();
这可以很容易地重写为:
if(running) return;
running = true;
runningHandle = Glib::signal_timeout().connect( sigc::mem_fun(*this, &ArtificialIntelligence::takeStep), 300 );
然后我只需要将runningHandle.disconnect();
添加到我的暂停功能中,并且一切都开始非常好。事实上,GUI响应的速度已经提高。
因此,如果其他人试图“采取行动,然后睡觉”过程,这是一个更好的选择。当然,应用程序中没有设置周期性,然后应该寻求其他解决方案。