2010-03-02 169 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函數也會對其他控件造成問題。