2010-03-02 104 views
0

我在Windows(Win32,C/C++)上使用Scintilla编辑控件。该控件在WndProc中创建。我有第二个线程,使用Boost.Thread创建,充当拼写检查器,并用红色的错误拼写错误地拼写单词。因此,我有两个线程改变了Scintilla控件的内容。Scintilla和线程安全

起初,编辑文本时程序崩溃。所以我研究了Scintilla的线程安全性。我找到的资料很少,但我设法得到这个引用文档中:

直接调用会导致如果从不同的线程 的Scintilla的 窗口的本地线程执行 问题,在这种情况下 的SendMessage( hSciWnd,SCI_ *,wParam, lParam)应该用于同步 与窗口的线程。

当然,我使用直接调用,因此我将拼写检查线程中的所有调用更改为SendMessage,现在程序不再崩溃。 最后,这就是问题,我解决了这个问题,还是我会遇到其他与Scintilla和多线程的怪癖?

+0

retagged boost.thread to boost-thread与其他boost库标签一致 – rcollyer 2010-05-06 14:12:15

回答

3

您通常只能从Windows中创建的线程访问Windows中的窗口(HWND)。发送到窗口的任何消息都将在创建它的线程中执行,这就是为什么当您全部替换掉​​时崩溃停止的原因通过发送消息直接调用Scintilla函数。如果您在拼写检查的线程使用SendMessage()这将导致以下情况发生:

  • 拼写检查线程将阻塞
  • 上下文切换到GUI线程将被执行
  • 消息循环将处理该消息(但不一定立即,队列中的消息将按照它们添加的顺序处理,因此只有在处理完所有先前添加的消息之后才会处理该消息)
  • 上下文切换到拼写检查线程将被执行
  • SendMessage()致电返回结果

所以你确实已经解决了这个问题,但价格非常高。每个拼写错误字都会导致两个线程上下文切换,并且拼写检查会阻止每个拼写错误字。如果其他需要很长时间处理的其他消息仍在排队,这实际上可能会持续很长时间。

您应该更改程序的设计。理想情况下,两个线程都可以独立工作,这可以通过添加一个线程安全的数据结构来实现,拼写检查线程将关于拼写错误的单词添加到信息中,并且主线程从中检索信息。 Boost有很多课程可以帮助你。通过这样做,您可以继续使用直接调用,因为它们将在主线程的上下文中执行。性能应该会提高,因为一次可以强调多个词汇,只会重新控制一次。如果使用PostMessage()而不是SendMessage(),则拼写检查线程将能够继续工作,而不依赖主线程准备处理该消息。

如果你记得永远不要从辅助线程调用任何Scintilla代码,你将不会遇到其他的怪癖。这并不是什么特定于Scintilla控件,调用内部不使用Windows消息的Windows API函数也会对其他控件造成问题。