C 闪烁与线程安全

C 闪烁与线程安全,c,multithreading,winapi,boost-thread,scintilla,C,Multithreading,Winapi,Boost Thread,Scintilla,我在Windows(Win32,C/C++)上使用闪烁编辑控件。控件是在WndProc中创建的。我还有第二个线程,是用Boost.thread创建的,它充当拼写检查器,并用拼写错误的红色波浪线标记单词。因此,我有两个线程改变闪烁控件的内容 起初,程序在编辑文本时崩溃。所以我研究了斯金特拉的线程安全性。我发现几乎没有什么信息,但我设法在文档中找到了这句话: 如果出现以下情况,直接呼叫将导致问题: 从不同的线程执行到 闪烁体的本机线程 窗口在哪种情况下 发送消息(hSciWnd、SCI_*和wPar

我在Windows(Win32,C/C++)上使用闪烁编辑控件。控件是在WndProc中创建的。我还有第二个线程,是用Boost.thread创建的,它充当拼写检查器,并用拼写错误的红色波浪线标记单词。因此,我有两个线程改变闪烁控件的内容

起初,程序在编辑文本时崩溃。所以我研究了斯金特拉的线程安全性。我发现几乎没有什么信息,但我设法在文档中找到了这句话:

如果出现以下情况,直接呼叫将导致问题: 从不同的线程执行到 闪烁体的本机线程 窗口在哪种情况下 发送消息(hSciWnd、SCI_*和wParam、, lParam)应用于同步 用窗户的线

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

通常,您应该仅从创建windows中的线程访问windows中的windows(
HWND
s)。发送到窗口的任何消息都将在创建它的线程中执行,这就是为什么当您通过发送消息替换对闪烁函数的所有直接调用时,崩溃停止发生的原因。如果在拼写检查线程中使用
SendMessage()

  • 拼写检查线程将被阻止
  • 将执行到GUI线程的上下文切换
  • 消息循环将处理消息(但不一定是立即处理,队列中的消息将按照它们添加的顺序进行处理,因此只有在处理完之前添加的所有消息后才会处理消息)
  • 将执行到拼写检查线程的上下文切换
  • SendMessage()
    调用返回结果
所以你确实解决了这个问题,但代价很高。每个拼写错误的单词都将导致两个线程上下文切换,拼写检查将阻止每个拼写错误的单词。如果其他需要很长时间才能处理的消息仍在排队,那么这实际上可能需要很长时间

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


如果您记得从不从辅助线程调用任何闪烁代码,您将不会遇到其他怪癖。这并不是斯金特拉控件所特有的,调用内部不使用Windows消息的Windows API函数对任何其他控件都会有问题。

通常,您应该仅从创建Windows中的线程访问Windows中的Windows(
HWND
s)。发送到窗口的任何消息都将在创建它的线程中执行,这就是为什么当您通过发送消息替换对闪烁函数的所有直接调用时,崩溃停止发生的原因。如果在拼写检查线程中使用
SendMessage()

  • 拼写检查线程将被阻止
  • 将执行到GUI线程的上下文切换
  • 消息循环将处理消息(但不一定是立即处理,队列中的消息将按照它们添加的顺序进行处理,因此只有在处理完之前添加的所有消息后才会处理消息)
  • 将执行到拼写检查线程的上下文切换
  • SendMessage()
    调用返回结果
所以你确实解决了这个问题,但代价很高。每个拼写错误的单词都将导致两个线程上下文切换,拼写检查将阻止每个拼写错误的单词。如果其他需要很长时间才能处理的消息仍在排队,那么这实际上可能需要很长时间

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


如果您记得从不从辅助线程调用任何闪烁代码,您将不会遇到其他怪癖。这并不是闪烁控制的特例,调用内部不使用Windows消息的Windows API函数对于任何其他控件都会有问题。

重新标记boost.thread到boost线程以与其他boost库标记一致标记boost.thread到boost线程以与其他boost库标记一致