2015-07-12 15 views
5

Tôi đang cố viết ứng dụng gtkmm sử dụng đa luồng C++ 11. Tuy nhiên, tôi tiếp tục chạy vào lỗi Fatal IO error 11 (Resource temporarily unavailable) on X server.Làm thế nào để chống lại "Lỗi IO Fatal 11 (Tài nguyên tạm thời không khả dụng) trên máy chủ X" trong ứng dụng gtkmm đa luồng?

Tôi có một số đối tượng Gtk::Image trên cửa sổ của mình. Mỗi người có một số Gtk::EventBox và định kỳ tôi phải thay đổi hình ảnh. Để làm điều đó tôi đã tạo ra một lớp chứa hộp sự kiện cho khối cụ thể, và nó có một chức năng loại bỏ hình ảnh trước đó, tạo ra một hình mới và đặt nó ở đó.

Dưới đây là một khối mã:

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

Khi error 11 xảy ra một số các số không được in để std::cerr, nhưng mà vấn đề xảy ra là khác nhau mỗi lần (i thời gian gần đây đã quan sát thấy nó đâm sau 12 và sau 123). Vì vậy, tôi đi đến kết luận rằng tài nguyên đang được sử dụng ở đâu đó không phải là hình ảnh, mà là eventBox. Nhưng sau khi khởi tạo chương trình, nó không được truy cập bất cứ nơi nào bên ngoài chức năng này, và chức năng này được bọc với khóa std::atomic_flag.

Câu hỏi: Điều gì có thể là lý do cho hành vi như vậy? Tôi có thể đảm bảo rằng nó không xảy ra? Hoặc tôi có thể bắt lỗi này và mong muốn phục hồi từ nó?

Chỉnh sửa:

tôi đã cố gắng

  1. Tôi cố gắng để thay đổi từ việc sử dụng std::thread-Glib::Threads::Thread, nhưng không có kết quả, vẫn nhận được lỗi tương tự.
  2. Đã đọc this tôi đã cố thêm GDK_SYNCHRONIZE vào môi trường, điều này đã tạo ra lỗi [xcb] Unknown request in queue while dequeuing/[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called. Điều này dẫn tôi đến this post, sau đó tôi đã cố gắng gọi XInitThreads() trước khi bắt đầu chủ đề mới (cả hai thông qua Glib::Threads::Threadstd::thread), nhưng điều này không có gì tích cực; ngoại trừ một lần bởi một số fluke các chủ đề đã thực sự thực hiện toàn bộ chức năng (hiển thị '4' trên màn hình), nhưng sau đó vẫn quản lý để chết với cùng một thông báo error 11.

Trả lời

2

Cuối cùng ở đây là cách tôi đã giải quyết tất cả các sự cố.

Đi qua liên kết được cung cấp bởi Phillip tôi đã tìm hiểu về Glib::signal_timeout() và điều đó đã giúp tôi hoàn toàn suy nghĩ lại khái niệm song song trong mã của tôi.

Dưới đây là những gì tôi đã phải bắt đầu với:

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

và điều này có thể dễ dàng được viết lại như sau:

if(running) return; 
running = true; 

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

sau đó tôi chỉ cần thêm runningHandle.disconnect(); chức năng tạm dừng của tôi, và tất cả bắt đầu làm việc tuyệt vời. Trong thực tế, tốc độ của phản ứng GUI đã tăng lên.

Vì vậy, nếu bất kỳ ai khác đang cố gắng thực hiện "thực hiện hành động, sau đó ngủ", đây là một lựa chọn tốt hơn nhiều. Có những ứng dụng khóa học mà không có chu kỳ thiết lập, và sau đó một số giải pháp khác nên được tìm kiếm.

Các vấn đề liên quan