Проблемы с потоками Qt в Linux

Я уже некоторое время разрабатываю свой проект с помощью Qt, и мы начинаем переходить к более многопоточному дизайну. При перемещении некоторых виджетов рендеринга GL в другие потоки я обнаружил очень странное поведение. Похоже, что если GL Widget начинает обновляться из другого потока (boost thread или QThread) до того, как виджет, который принимает пользовательский ввод (например, QTextEdit), захватывает фокус, я получаю сбои XCB, которые выглядят следующим образом:

[xcb] Too much data requested from _XRead
[xcb] This is most likely caused by a broken X extension library
[xcb] Aborting, sorry about that.
hypnotizer: ../../src/xcb_io.c:735: _XRead: Assertion ‘!xcb_xlib_too_much_data_requested’ failed.

Чтобы проверить это, я на самом деле могу сделать простую модификацию демо-версии GLHypnotizer, чтобы воспроизвести сбой. Эту демонстрацию можно найти здесь: http://qt-project.org/doc/qt-4.8/demos-glhypnotizer.html [qt-project.org]

Если я добавлю строку «mdiArea.addSubWindow(new QTextEdit(this));» примерно в строке 313 (перед вызовом newThread()), то при запуске демонстрации будет QTextEdit и виджет GL Hypnotizer. Если я затем нажму на QTextEdit, чтобы захватить фокус, я каждый раз буду получать вышеупомянутый сбой.

Может ли кто-нибудь воспроизвести ошибку при установке Linux, используя приведенные выше инструкции? Кто-нибудь сталкивался с такими проблемами в Linux, используя Qt и многопоточность раньше?

Примечание. Я использую Ubuntu 12, и этот сбой происходит в установках VirtualBox и Ubuntu, отличных от VirtualBox.


person kelano    schedule 16.10.2012    source источник
comment
Вы когда-нибудь получали решение?   -  person 246tNt    schedule 30.06.2016


Ответы (1)


OpenGL, рендеринг Qt и многопоточность плохо сочетаются. В частности, контекст OpenGL может быть активен одновременно только в одном потоке. Теперь, если контекст используется несколькими виджетами (обратите внимание, что это отличается от совместного использования объектов между контекстами, я говорю об одном контексте, который используется для нескольких окон/виджетов, что является законным), и эти виджеты отображаются из разных потоков, которые вы собираетесь вникать во многие проблемы.

Обычно лучший способ действий, когда дело доходит до OpenGL и многопоточности, — не делать этого. Используйте несколько потоков, да, но используйте их для всего, что не связано с OpenGL или каким-либо видом вывода графики. Выполняйте все графические операции в одном потоке, чтобы избежать серьезных проблем.

person datenwolf    schedule 16.10.2012
comment
Qt и многопоточность плохо сочетаются? Или это OpenGL и многопоточность, которые плохо сочетаются? - person Chris; 16.10.2012
comment
@Chris: О, спасибо, это действительно была непреднамеренная опечатка. Это OpenGL, который не очень хорошо справляется с многопоточностью. Но у Qt также есть проблемы с многопоточностью, когда дело доходит до рендеринга. Таким образом, смешивая функции рисования Qt, OpenGL и многопоточность, вы получаете рецепт для больших головных болей. - person datenwolf; 16.10.2012
comment
Связанная демонстрация Qt выглядит так, как будто это официальная демонстрация и, следовательно, хороший код. Более того, kelano сказал, что это работает до тех пор, пока не будет добавлен виджет QT textedit, который, я бы не подумал, связан с OpenGL. Кроме того, это ошибка XCB. - person Abe Schneider; 16.10.2012
comment
Как указал пользователь выше меня, он падает даже с одним потоком openGL, работающим вне потока Qt, поэтому я не уверен, что это проблема OpenGL из нескольких потоков. - person kelano; 16.10.2012
comment
@kelano: обычно Qt выполняет весь рендеринг в специальном потоке рендеринга. Этот поток также обычно вызывает обработчик рисования QGLWidget или класса-потомка. Теперь, когда виджет, такой как QTextEdit, получает фокус, он должен визуально отражать изменение своего состояния, т.е. что-то рисовать; теперь может случиться так, что привязка контекста OpenGL в другом потоке и выполнение там команд может нарушить работу Qt или использование ею определенных расширений X. - person datenwolf; 16.10.2012
comment
@datenwolf: Ах, я никогда не рассматривал возможность TextEdit в основном потоке с использованием контекста OpenGL. Если это так, то мне, возможно, придется переосмыслить эту структуру. Что меня все еще смущает, так это то, как я могу иметь более 20 OpenGL QThreads, работающих в примере без заминок, но в тот момент, когда я нажимаю на этот TextEdit, он падает. - person kelano; 16.10.2012
comment
@kelano: это вполне может быть ошибка Qt. Но могу я спросить вас: почему у вас есть 20 потоков, выполняющих OpenGL? Только самые последние графические процессоры могут фактически выполнять параллельный рендеринг OpenGL и не очень быстро. Лучше выполнять все операции OpenGL в одном потоке и, возможно, иметь один вспомогательный поток для подготовки данных. - person datenwolf; 17.10.2012
comment
@datenwolf: В моем собственном приложении есть один выделенный поток рендеринга OpenGL. Однако в основном потоке Qt у меня есть QTextEdit, который, кажется, вызывает проблемы, которые я воспроизвожу в демо. Моя ссылка на 20 потоков была направлена ​​на демонстрацию Hypnotizer, в которой у меня может быть 20 потоков GL, работающих нормально, но в тот момент, когда я касаюсь TextEdit, происходит сбой. Я полагаю, что GLThreads в демоверсии имеют какой-то механизм безопасности, который основной поток не использует (например, вызов makeCurrent) - person kelano; 17.10.2012
comment
Просто чтобы добавить, вот официальное сообщение в блоге Qt, в котором утверждается, что это возможно со ссылкой на демонстрацию: blog.qt.digia.com/2011/06/03/threaded-opengl-in-4-8 - person Abe Schneider; 17.10.2012