Codegear / Borland ActiveX threading Synchronization problems

This is a quick reference post to help anyone having problems working with Borland’s / Codegear’s TActiveForm and Synchronizing TThread’s with the VCL’s main thread (as is required for UI type code changes). After experiencing very strange behaviour for months I came across: this link which explains the problem, when it was introduced, and how to overcome it. According to the link above this modified behaviour started with Delphi 6 (so Builder 5 or 6? is my guess).

This surfaced in one of my projects when I noticed period application “hanging” or freeze when threaded operations tried to call TThreads Synchronize or even when calling SendMessage or PostMessage. Interestingly the hang issue is more pronounced when your activeX control is hosted by Internet Explorer 6. IE 7 seems to behave much better. To solve the problem I followed the first part of the article linked to above and hooked into the VCL’s Classes::WakeMainThread callback method. In case the above article dissappears here is the Pascal code (which I easily ported to C++):

const WM_CLSYNCHRONIZE = WM_USER + 1;
...
type
TActiveFormX = class(TActiveForm, IActiveFormX)
procedure WMclSynchronize(var Message: TMessage); message WM_CLSYNCHRONIZE;
...
procedure TActiveFormX.ActiveFormCreate(Sender: TObject);
begin
Classes.WakeMainThread := DoOnWakeMainThread;
end;
...
procedure TActiveFormX.DoOnWakeMainThread(Sender: TObject);
begin
PostMessage(Self.Handle, WM_CLSYNCHRONIZE, 0, 0);
end;
...
procedure TActiveFormX.WMclSynchronize(var Message: TMessage);
begin
Classes.CheckSynchronize();
end;

Once this was added, no more random madness, thread synchronization returned to normal!


2 Responses to Codegear / Borland ActiveX threading Synchronization problems

  1. Hi Mark,
    i’m an italian C++ programmer and i stumbled in a very similar problem…
    Can you please post your c++ code? i have some trouble gettin in from the delphi sample….

    Thanks 🙂

  2. In the header file of your class that derives from TActiveForm add the following:

    void __fastcall DoWakeMainThread(TObject *Sender);
    void __fastcall WMCLSynchronize(TMessage &msg);

    Then in the corresponding cpp file:

    void __fastcall TmyActiveForm::DoWakeMainThread(TObject *Sender)
    {
    PostMessage(this->Handle, WM_CLSYNCHRONIZE. 0, 0);
    }

    void __fastcall TmyActiveForm::WMCLSynchronize(TMessage &msg)
    {
    Classes::CheckSynchronize();
    }

    then you need to assign the custom DoWakeMainThread to the VCL’s global WakeMainThread handler but adding the following line of code somewhere (like a startup method or perhaps the constructor)

    Classes::WakeMainThread = DoWakeMainThread;

    And that is it.