Сцинтилла и нить безопасности - PullRequest
0 голосов
/ 03 марта 2010

Я использую элемент управления редактирования Scintilla в Windows (Win32, C / C ++). Элемент управления создан в WndProc. У меня есть вторая нить, созданная с помощью Boost.Thread, которая выполняет функцию проверки орфографии и помечает красным заглушением неправильно написанные слова. Поэтому у меня есть два потока, изменяющие содержимое элемента управления Scintilla.

Сначала программа зависала при редактировании текста. Поэтому я исследовал Scintilla для безопасности потоков. Я нашел мало информации, но мне удалось получить эту цитату в документации:

прямой вызов вызовет проблемы, если выполняется из другого потока родная нить сцинтиллы окно в этом случае SendMessage (hSciWnd, SCI_ *, wParam, lParam) должен использоваться для синхронизации с резьбой окна.

Конечно, я использую прямые вызовы, поэтому я изменяю все вызовы в потоке проверки орфографии на SendMessage, и теперь программа больше не падает. Наконец, и вот в чем вопрос: решил ли я проблему или столкнусь с другими причудами со Scintilla и многопоточностью?

1 Ответ

3 голосов
/ 03 марта 2010

Обычно вы должны получать доступ к окнам (HWND s) в Windows только из потока, в котором они были созданы. Любое сообщение, отправленное окну, будет выполняться в потоке, который его создал, поэтому сбои прекратились, когда вы заменили все прямые вызовы функций Scintilla путем отправки сообщений. Если вы используете SendMessage() в своей цепочке проверки орфографии, это приведет к следующему:

  • поток проверки орфографии заблокирует
  • будет выполнено переключение контекста в поток GUI
  • цикл обработки сообщений обработает сообщение (но не обязательно сразу, сообщения в очереди будут обрабатываться в порядке их добавления, поэтому сообщение будет обрабатываться только после обработки всех ранее добавленных сообщений)
  • будет выполнено переключение контекста в поток проверки орфографии
  • вызов SendMessage() возвращает результат

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

Вам следует изменить дизайн вашей программы. В идеале оба потока смогут работать независимо друг от друга, и этого можно достичь, добавив потокобезопасную структуру данных, в которую поток проверки орфографии добавляет информацию о словах с ошибками и откуда основной поток получает информацию. Boost имеет много классов, чтобы помочь вам. Тем самым вы можете продолжать использовать прямые вызовы, так как они будут выполняться в контексте основного потока. Производительность должна улучшиться, так как несколько слов могут быть подчеркнуты за один раз, вызывая только одну перерисовку элемента управления. Если вы используете PostMessage() вместо SendMessage(), поток проверки орфографии сможет продолжить свою работу независимо от того, будет ли основной поток готов обработать сообщение.

Если вы помните, что никогда не вызывали какой-либо код Scintilla из вторичных потоков, вы не столкнетесь с другими причудами. И это не является чем-то конкретным для элемента управления Scintilla, вызывая функции Windows API, которые не используют сообщения Windows внутри, было бы проблематично для любого другого элемента управления.

...