Обычно вы должны получать доступ к окнам (HWND
s) в Windows только из потока, в котором они были созданы. Любое сообщение, отправленное окну, будет выполняться в потоке, который его создал, поэтому сбои прекратились, когда вы заменили все прямые вызовы функций Scintilla путем отправки сообщений. Если вы используете SendMessage()
в своей цепочке проверки орфографии, это приведет к следующему:
- поток проверки орфографии заблокирует
- будет выполнено переключение контекста в поток GUI
- цикл обработки сообщений обработает сообщение (но не обязательно сразу, сообщения в очереди будут обрабатываться в порядке их добавления, поэтому сообщение будет обрабатываться только после обработки всех ранее добавленных сообщений)
- будет выполнено переключение контекста в поток проверки орфографии
- вызов
SendMessage()
возвращает результат
Итак, вы действительно исправили проблему, но по очень высокой цене. Каждое слово с ошибкой будет вызывать два переключения контекста потока, и проверка орфографии будет блокироваться для каждого слова с ошибкой. На самом деле это может занять довольно много времени, если какие-либо другие сообщения, для обработки которых требуется много времени, все еще находятся в очереди.
Вам следует изменить дизайн вашей программы. В идеале оба потока смогут работать независимо друг от друга, и этого можно достичь, добавив потокобезопасную структуру данных, в которую поток проверки орфографии добавляет информацию о словах с ошибками и откуда основной поток получает информацию. Boost имеет много классов, чтобы помочь вам. Тем самым вы можете продолжать использовать прямые вызовы, так как они будут выполняться в контексте основного потока. Производительность должна улучшиться, так как несколько слов могут быть подчеркнуты за один раз, вызывая только одну перерисовку элемента управления. Если вы используете PostMessage()
вместо SendMessage()
, поток проверки орфографии сможет продолжить свою работу независимо от того, будет ли основной поток готов обработать сообщение.
Если вы помните, что никогда не вызывали какой-либо код Scintilla из вторичных потоков, вы не столкнетесь с другими причудами. И это не является чем-то конкретным для элемента управления Scintilla, вызывая функции Windows API, которые не используют сообщения Windows внутри, было бы проблематично для любого другого элемента управления.