2015-07-12 8 views
5

Ich versuche, eine GTKMM-Anwendung zu schreiben, die C++ 11 Multithreading verwendet. Allerdings laufe ich weiter in Fatal IO error 11 (Resource temporarily unavailable) on X server Fehler.Wie bekämpft man "Fatal IO Fehler 11 (Ressource vorübergehend nicht verfügbar) auf X-Server" in Multithread gtkmm-Anwendung?

Ich habe mehrere Gtk::Image Objekte auf meinem Fenster. Jeder ist in seinem eigenen Gtk::EventBox und in regelmäßigen Abständen muss ich das Bild ändern. Um dies zu tun, habe ich eine Klasse erstellt, die die Ereignisbox für den spezifischen Block enthält, und es hat eine Funktion, die das vorherige Bild entfernt, das neue erzeugt und es dort platziert.

Hier ist ein Code-Block:

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(); 

Wenn error 11 einige der Zahlen fällt std::cerr werden nicht gedruckt, aber wo das Problem geschieht, ist jedes Mal anders (ich habe beobachtet, vor kurzem nach 12 abstürzt und nach 123). So komme ich zum Schluss, dass die Ressource, die irgendwo benutzt wird, nicht das Bild ist, sondern die eventBox. Nach der Initialisierung des Programms wird jedoch nirgends außerhalb dieser Funktion auf diese Funktion zugegriffen, und diese Funktion wird mit der std::atomic_flag-Sperre umschlossen.

Fragen: Was kann ein Grund für ein solches Verhalten sein? Kann ich sicherstellen, dass es nicht passiert? Oder kann ich diesen Fehler abfangen und erwarten, dass ich mich davon erholen kann?

Edits:

Ich habe

versucht von
  1. Ich habe versucht, ändern std::thread-Glib::Threads::Thread verwenden, aber ohne Erfolg, immer noch die gleichen Fehler.
  2. Nachdem ich this gelesen habe, habe ich versucht, GDK_SYNCHRONIZE zur Umgebung hinzuzufügen, dieses hat [xcb] Unknown request in queue while dequeuing/[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called Fehler erzeugt. Dies führte mich zu this post, nach dem ich versucht habe, XInitThreads() vor dem Start der neuen Thread (beide über Glib::Threads::Thread und std::thread), aber dies tat nichts positives; Abgesehen davon, dass der Thread einmal durch irgendeinen Zufall die gesamte Funktion ausgeführt hat (auf dem Bildschirm wird "4" angezeigt), ist es dann aber trotzdem gelungen, mit der gleichen error 11 Nachricht zu sterben.

Antwort

2

Am Ende hier ist, wie ich alle Probleme gelöst habe.

Durch den von Phillip bereitgestellten Link habe ich über Glib::signal_timeout() herausgefunden, und das hat mir ermöglicht, das Konzept der Parallelität in meinem Code vollständig zu überdenken.

Hier ist, was ich hatte, mit zu beginnen:

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(); 

und diese leicht umgeschrieben werden könnte, wie:

if(running) return; 
running = true; 

runningHandle = Glib::signal_timeout().connect(sigc::mem_fun(*this, &ArtificialIntelligence::takeStep), 300); 

ich dann brauchte nur runningHandle.disconnect(); meiner Pause-Funktion hinzuzufügen, und alles begann wunderbar funktioniert. Tatsächlich ist die Geschwindigkeit der GUI-Reaktion gestiegen.

Also wenn jemand anderes versucht zu tun "eine Aktion, dann schlafen" Prozess, ist dies eine viel bessere Alternative. Es gibt natürlich Anwendungen, bei denen es keine festgelegte Periodizität gibt, und dann sollte eine andere Lösung gesucht werden.