Page 1 of 1

TRVWordEnumThread.Stop hangs spelling in suspended state

Posted: Thu Jan 08, 2009 6:47 am
by lwinter
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

Posted: Thu Jan 08, 2009 1:43 pm
by Sergey Tkachenko
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.

Posted: Mon Jan 12, 2009 8:24 am
by lwinter
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

Posted: Mon Jan 12, 2009 10:04 am
by Sergey Tkachenko
I am afraid no, there is no method for checking document (adding red underlines) without using a thread.

Solution: use WakeMainThread to call CheckSynchronize

Posted: Tue Feb 17, 2009 4:23 am
by lwinter
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;