- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我在 Windows(Win32、C/C++)上使用 Scintilla 编辑控件。该控件是在 WndProc 中创建的。我有第二个线程,使用 Boost.Thread 创建,它充当拼写检查器并用红色波浪线标记拼写错误的单词。因此,我有两个线程更改 Scintilla 控件的内容。
起初,程序在编辑文本时崩溃。所以我研究了 Scintilla 的线程安全性。我发现的信息很少,但我设法在文档中引用了这句话:
direct calling will cause problems if performed from a different thread to the native thread of the Scintilla window in which case SendMessage(hSciWnd, SCI_*, wParam, lParam) should be used to synchronize with the window's thread.
当然,我使用的是直接调用,因此我将拼写检查线程中的所有调用更改为 SendMessage,现在程序不会再崩溃了。最后,这就是问题,我是否解决了问题,或者我是否会遇到 Scintilla 和多线程的其他怪癖?
最佳答案
您通常应该只从创建它们的线程访问 Windows 中的窗口(HWND
)。发送到窗口的任何消息都将在创建它的线程中执行,这就是崩溃的原因当您通过发送消息替换对 Scintilla 函数的所有直接调用时,这种情况就停止了。如果您在拼写检查线程中使用 SendMessage()
,这将导致发生以下情况:
SendMessage()
调用返回结果所以你确实解决了这个问题,但是付出了很高的代价。每个拼错的单词都会导致两次线程上下文切换,拼写检查会因每个拼错的单词而阻塞。如果需要很长时间处理的任何其他消息仍在排队,这实际上可能会花费很长时间。
您应该更改程序的设计。理想情况下,两个线程都能够独立工作,这可以通过添加一个线程安全的数据结构来实现,拼写检查线程将有关拼写错误的单词的信息添加到该数据结构中,主线程从中检索信息。 Boost 有很多类可以帮助你。通过这样做,您可以继续使用直接调用,因为它们将在主线程的上下文中执行。性能应该会提高,因为多个单词可能会被一次性加下划线,从而只导致一次控件重绘。如果您使用 PostMessage()
而不是 SendMessage()
,拼写检查线程将能够独立于主线程准备好处理消息继续其工作。
如果您记得永远不要从辅助线程调用任何 Scintilla 代码,您就不会遇到其他怪癖。这并不是 Scintilla 控件所特有的,调用内部不使用 Windows 消息的 Windows API 函数对于任何其他控件也会有问题。
关于c - Scintilla 和线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2367633/
我是一名优秀的程序员,十分优秀!