Frage

Ich verwende das Scintilla-Bearbeitungssteuerelement unter Windows (Win32, C/C++).Das Steuerelement wird in WndProc erstellt.Ich habe einen zweiten Thread, der mit Boost.Thread erstellt wurde und als Rechtschreibprüfung fungiert und falsch geschriebene Wörter mit einem roten Kringel markiert.Daher habe ich zwei Threads, die den Inhalt des Scintilla-Steuerelements ändern.

Beim Bearbeiten von Text stürzte das Programm zunächst ab.Deshalb habe ich bei Scintilla nach Thread-Sicherheit gesucht.Ich habe nur wenige Informationen gefunden, aber es gelingt mir, dieses Zitat in der Dokumentation zu finden:

Direkte Anrufe verursachen Probleme, wenn sie von einem anderen Thread in den nativen Thread des Szintilla -Fensters ausgeführt werden. In diesem Fall sollte SendMessage (HSCIWND, SCI_*, WPARAM, LPARAM) verwendet werden, um mit dem Fenster -Thread zu synchronisieren.

Natürlich verwende ich Direktaufrufe, dementsprechend ändere ich alle Aufrufe im Rechtschreibprüfungsthread auf SendMessage und jetzt stürzt das Programm nicht mehr ab.Schließlich, und das ist die Frage, habe ich das Problem gelöst, oder werde ich bei Scintilla und Multithreads auf andere Macken stoßen?

War es hilfreich?

Lösung

Sie sollten im Allgemeinen auf Windows zugreifen (HWNDs) in Windows nur aus dem Thread, in dem sie erstellt wurden.Jede an das Fenster gesendete Nachricht wird in dem Thread ausgeführt, der sie erstellt hat. Aus diesem Grund traten keine Abstürze mehr auf, als Sie alle direkten Aufrufe der Scintilla-Funktionen durch das Senden von Nachrichten ersetzten.Wenn du benutzt SendMessage() In Ihrem Thread zur Rechtschreibprüfung führt dies dazu, dass Folgendes passiert:

  • Der Thread zur Rechtschreibprüfung wird blockiert
  • Es wird ein Kontextwechsel zum GUI-Thread durchgeführt
  • Die Nachrichtenschleife verarbeitet die Nachricht (aber nicht unbedingt sofort, Nachrichten in der Warteschlange werden in der Reihenfolge verarbeitet, in der sie hinzugefügt wurden, sodass die Nachricht erst verarbeitet wird, nachdem alle zuvor hinzugefügten Nachrichten verarbeitet wurden).
  • Es wird ein Kontextwechsel zum Rechtschreibprüfungsthread durchgeführt
  • Die SendMessage() Aufruf gibt das Ergebnis zurück

Sie haben das Problem also zwar behoben, allerdings zu einem sehr hohen Preis.Jedes falsch geschriebene Wort führt zu zwei Thread-Kontextwechseln und die Rechtschreibprüfung wird für jedes falsch geschriebene Wort blockiert.Dies könnte tatsächlich ziemlich lange dauern, wenn noch andere Nachrichten in der Warteschlange wären, deren Bearbeitung lange dauert.

Sie sollten das Design Ihres Programms ändern.Im Idealfall können beide Threads unabhängig voneinander arbeiten. Dies kann durch Hinzufügen einer Thread-sicheren Datenstruktur erreicht werden, zu der der Rechtschreibprüfungs-Thread Informationen über falsch geschriebene Wörter hinzufügt und aus der der Haupt-Thread die Informationen abruft.Boost bietet viele Kurse, die Ihnen helfen.Auf diese Weise können Sie die direkten Aufrufe weiterhin verwenden, da diese im Kontext des Hauptthreads ausgeführt werden.Die Leistung sollte sich verbessern, da mehrere Wörter auf einmal unterstrichen werden könnten, was nur eine einzige Neuzeichnung des Steuerelements zur Folge hätte.Wenn du benutzt PostMessage() anstatt SendMessage() Der Rechtschreibprüfungs-Thread kann seine Arbeit unabhängig davon fortsetzen, ob der Haupt-Thread bereit ist, die Nachricht zu verarbeiten.

Wenn Sie daran denken, niemals Scintilla-Code aus sekundären Threads aufzurufen, werden Sie nicht auf andere Macken stoßen.Und das ist nichts Spezifisches für das Scintilla-Steuerelement. Der Aufruf von Windows-API-Funktionen, die intern keine Windows-Nachrichten verwenden, wäre auch für jedes andere Steuerelement problematisch.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top