TRVWordEnumThread.Stop hangs spelling in suspended state

General TRichView support forum. Please post your questions here
Post Reply
lwinter
Posts: 24
Joined: Thu Dec 01, 2005 4:42 am

TRVWordEnumThread.Stop hangs spelling in suspended state

Post 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
Sergey Tkachenko
Site Admin
Posts: 17602
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post 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.
lwinter
Posts: 24
Joined: Thu Dec 01, 2005 4:42 am

Post 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
Sergey Tkachenko
Site Admin
Posts: 17602
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

I am afraid no, there is no method for checking document (adding red underlines) without using a thread.
lwinter
Posts: 24
Joined: Thu Dec 01, 2005 4:42 am

Solution: use WakeMainThread to call CheckSynchronize

Post 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; 
Post Reply