CONTEXT:
I use RichView with AddictSpeller compiled into one single DLL - used by an application written in Smalltalk. No Delphi forms, only RichView controls inside the Smalltalk-application's windows.
Using Delphi 5 / RichView 1.9 / AddictSpeller 3 had no problem with spelling.
Upgrading to codegearRAD Delphi 2007 (version 11) / RichView 10 / AddictSpeller 3.5 has a problem, although the code utilizing the speller has not changed (apart from using TRVAddictSpell3 instead TAddictSpell3).
PROBLEM:
In RichView 10, spelling stops working after a few words (squiggle lines stop drawing) - the TRVWordEnumThread gets into Suspend=true and never resumes spelling (never calls CheckSynchronise -> AddMisspelling from inside TRVWordEnumThread.Stop).
Unfortunately it is impractical to send a demo project/test case, as you would need the (Smalltalk) host application to test the DLL.
QUESTION:
Any hint, idea, guess or whatever would be much appreciated.
Thank you,
-- Lutz
TRVWordEnumThread.Stop hangs spelling in suspended state
-
- Site Admin
- Posts: 17602
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
There were changes in VCL thread code since Delphi 6. Probably the problem is because of them. In TRichView, there are places where the main process waits for the thread (to finish or to do some work). "Stop" method is one of these places.
Since the thread may call Synchronize method, making a simple cycle for waiting will cause a deadlock. To avoid a deadlock, TRichView uses CheckSynchronize function in Delphi 6+, while in the older versions it uses PeekMessage.
It looks like CheckSynchronize does not work properly in SmallTalk DLL.
You cannot use PeekMessage in Delphi 6+ for the same task, because it makes no sense: TThread.Synchronize is implemented differently, and synchronization must be implemented differently too.
Sorry, I cannot suggest a solution. Try googling for "checksynchronize dll". This article looks interesting: http://www.delphi3000.com/articles/article_4152.asp?SK= , but I am afraid the solution explained in it requires some work to implement.
Since the thread may call Synchronize method, making a simple cycle for waiting will cause a deadlock. To avoid a deadlock, TRichView uses CheckSynchronize function in Delphi 6+, while in the older versions it uses PeekMessage.
It looks like CheckSynchronize does not work properly in SmallTalk DLL.
You cannot use PeekMessage in Delphi 6+ for the same task, because it makes no sense: TThread.Synchronize is implemented differently, and synchronization must be implemented differently too.
Sorry, I cannot suggest a solution. Try googling for "checksynchronize dll". This article looks interesting: http://www.delphi3000.com/articles/article_4152.asp?SK= , but I am afraid the solution explained in it requires some work to implement.
CONFIRMED:
Yes, it seems that in the absence of Delphi's VCL components it is necessary to pump-in "Classes.CheckSynchronize" calls, like a pacemaker, to keep TRVWordEnumThread awake.
This partially solves the problem, as words are being spellchecked and misspellings are added (drawing the squiggle line).
PROBLEM II:
Using a pacemaker, spelling executes one-at-a-time word-by-word at the speed of the pacemaker's timer interval.
This is a problem with pasting bigger chunks of text.
QUESTION:
Is there a function I can call to have the entire document checked (and misspellings added) all in one go - to be called on text pasted?
Thanks!
-- Lutz
Yes, it seems that in the absence of Delphi's VCL components it is necessary to pump-in "Classes.CheckSynchronize" calls, like a pacemaker, to keep TRVWordEnumThread awake.
This partially solves the problem, as words are being spellchecked and misspellings are added (drawing the squiggle line).
PROBLEM II:
Using a pacemaker, spelling executes one-at-a-time word-by-word at the speed of the pacemaker's timer interval.
This is a problem with pasting bigger chunks of text.
QUESTION:
Is there a function I can call to have the entire document checked (and misspellings added) all in one go - to be called on text pasted?
Thanks!
-- Lutz
-
- Site Admin
- Posts: 17602
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
Solution: use WakeMainThread to call CheckSynchronize
In the absence of VCL / Delphi forms, the synchronization queue is not processed - but the VCL synchronization feature can still be used. In this case, the appropriate way to synchronize threads (like TRVWordEnumThread), is to assign an event handler to the Classes.WakeMainThread which sends a message to a function which calls Classes.CheckSynchronize().
Code: Select all
const
WM_CLSYNCHRONIZE = WM_USER + 1;
type
CustomisedRichViewEditControl = class(TRichViewEdit)
procedure DoOnWakeMainThread(Sender: TObject);
procedure Make(...)
procedure WMclSynchronize(var Message: TMessage);
...
procedure CustomisedRichViewEditControl.Make(...)
begin
Classes.WakeMainThread := DoOnWakeMainThread;
end;
procedure CustomisedRichViewEditControl.DoOnWakeMainThread(Sender: TObject);
begin
PostMessage(Self.Handle, WM_CLSYNCHRONIZE, 0, 0);
end;
procedure CustomisedRichViewEditControl.WMclSynchronize(var Message: TMessage);
begin
Classes.CheckSynchronize();
end;