2015-07-12 28 views
5

我正在嘗試編寫一個使用C++ 11多線程的gtkmm應用程序。但是,我不斷遇到Fatal IO error 11 (Resource temporarily unavailable) on X server錯誤。如何打擊多線程gtkmm應用程序中的「X服務器上的致命IO錯誤11(資源暫時不可用)」?

我在窗口上有幾個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

問題:什麼可能是此類行爲的原因?我能確保它不會發生嗎?或者我可以捕獲這個錯誤,並期望從中恢復?

編輯:

我試圖

  1. 我試圖使用std::threadGlib::Threads::Thread改變,但無濟於事,仍然得到同樣的錯誤。
  2. 已讀this我試圖將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,之後我試圖在啓動新線程前(通過Glib::Threads::Threadstd::thread)呼叫XInitThreads(),但這沒有任何好處;除了一次通過一些僥倖實際上線程已經執行了整個功能(在屏幕上顯示'4'),但是仍然設法以相同的error 11消息去死。

回答

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響應的速度已經提高。

因此,如果任何人試圖做「採取行動,然後睡覺」的過程,這是一個更好的選擇。當然,沒有固定週期的應用,然後應該尋求其他解決方案。

相關問題