Research on main thread synchronization in DLL (sub-thread code is put into main thread for execution)

Source: Internet
Author: User

DLLResearch on Internal Thread Synchronization main thread (subthreadCodePut it in the main thread for execution)

 

We often use multi-thread programming in actual projects, such as socket programming. to synchronize the main thread within the created thread, we generally use the synchronize method to implement Sub-thread operations and put them in the main thread for execution, synchronize is very convenient to use, and anonymous methods can be used in versions 2009 and later, which brings great convenience to multithreading. However, it turns out that synchronize isProgram. If the requirements for running the synchronize method in the DLL program loaded by the main program are harsh, the DLL program must be copied to the main program, at the same time, The dll must have a form status of modal or the form in the main program must not be displayed. For details, see:

 

Main Program:

Unit mainfrm;

 

Interface

 

Uses

Windows, messages, sysutils, variants, classes, graphics, controls, forms,

Dialogs, stdctrls;

 

Type

Tmainform = Class (tform)

Btn1: tbutton;

Procedure btn1click (Sender: tobject );

Private

{Private Declarations}

Public

{Public declarations}

End;

 

VaR

Mainform: tmainform;

 

Implementation

 

{$ R *. DFM}

 

Procedure tmainform. btn1click (Sender: tobject );

VaR

Fhandle: thandle;

Opendllwindow: Procedure (amainhandle: integer); stdcall;

Begin

Fhandle: = loadlibrary (pchar ('dlprj. dll '));

If fhandle> 0 then

Begin

Opendllwindow: = getprocaddress (fhandle, pchar ('opendllwindow '));

 

If assigned (opendllwindow) then

Begin

Opendllwindow (application. Handle );

End;

End

Else

Showmessage ('dll loading failed! ');

End;

 

End.

 

DLLProgram:

Unit dllfrm;

 

Interface

 

Uses

Windows, messages, sysutils, variants, classes, graphics, controls, forms,

Dialogs;

 

Type

Tdllform = Class (tform)

Procedure formshow (Sender: tobject );

Private

{Private Declarations}

Public

{Public declarations}

End;

 

Type

Tdllthread = Class (tthread)

Protected

Procedure execute; override;

End;

 

VaR

Dllform: tdllform;

 

Implementation

 

{$ R *. DFM}

 

Procedure tdllthread. Execute;

VaR

Count: integer;

TP: tthreadprocedure;

Begin

Count: = 0;

While true do

Begin

Try

Synchronize (

Procedure

Begin

Showmessage (inttostr (count ));

Count: = count + 2000;

End

);

Except

// Ignore Error

End;

 

Sleep (2000); // pause for two seconds

End;

End;

 

Procedure opendllwindow (amainhandle: integer); stdcall;

Begin

If dllform = nil then

Dllform: = tdllform. Create (application );

 

// Copy to the main program

Application. Handle: = amainhandle;

Dllform. showmodal;

// Dllform. show;

End;

Exports opendllwindow;

 

 

Procedure tdllform. formshow (Sender: tobject );

VaR

Dllthread: tdllthread;

Begin

Dllthread: = tdllthread. Create (false );

End;

 

End.

The above Code uses the synchronize method to synchronize the master thread and can run normally. However, if we remove application. Handle: = amainhandle from the opendllwindow method in the DLL project, or change the code dllform. showmodal; To dllform. Show, the thread will be blocked when synchronizing data to the main thread.

In this case, if the form display mode is not modal after the main program is loaded in the DLL project, we will not be able to use the convenient synchronize method. In this way, it is necessary to use sendmessage to send messages to the main thread. For example, we need to change the code in the DLL project as follows:

Unit dllfrm;

 

Interface

 

Uses

Windows, messages, sysutils, variants, classes, graphics, controls, forms,

Dialogs;

 

Type

Tdllform = Class (tform)

Procedure formshow (Sender: tobject );

Private

{Private Declarations}

Public

{Public declarations}

Procedure wmrefreshform (var msg: tmessage); message wm_user + 100;

End;

 

Type

Tdllthread = Class (tthread)

Protected

Procedure execute; override;

End;

 

VaR

Dllform: tdllform;

 

Implementation

 

{$ R *. DFM}

 

Procedure tdllthread. Execute;

VaR

Count: integer;

TP: tthreadprocedure;

Begin

Count: = 0;

While true do

Begin

Try

Sendmessage (dllform. Handle, wm_user+ 100, Count, 0 );

Count: = count + 2000;

Except

// Ignore Error

End;

 

Sleep (2000 );

End;

End;

 

Procedure opendllwindow (amainhandle: integer); stdcall;

Begin

If dllform = nil then

Dllform: = tdllform. Create (application );

 

// Copy to the main program

// Application. Handle: = amainhandle;

// Dllform. showmodal;

Dllform. show;

End;

Exports opendllwindow;

 

 

Procedure tdllform. formshow (Sender: tobject );

VaR

Dllthread: tdllthread;

Begin

Dllthread: = tdllthread. Create (false );

End;

 

Procedure tdllform. wmrefreshform (var msg: tmessage );

Begin

If msg. MSG = wm_user + 100 then

Begin

Showmessage (inttostr (msg. wparam ));

End;

End;

 

End.

In this way, our DLL program will work normally, which is also a common method. However, if we have frequent synchronization operations in the thread, or these synchronization operations will use a large number of internal variables in the thread, sendmessage will be troublesome and difficult. If we can customize the anonymous method in the thread execution method, just like using synchronize, the amount of code will be greatly reduced and the programming process will be greatly simplified, in this way, we think of passing the pointer of the anonymous method as a parameter of sendmessage to a custom message, and then executing this anonymous method in the custom message. We are glad that this is okay. Modify the code in the DLL project as follows:

Unit dllfrm;

 

Interface

 

Uses

Windows, messages, sysutils, variants, classes, graphics, controls, forms,

Dialogs;

 

Type

Tdllform = Class (tform)

Procedure formshow (Sender: tobject );

Private

{Private Declarations}

Public

{Public declarations}

Procedure wmrefreshform (var msg: tmessage); message wm_user + 100;

End;

 

Type

Tdllthread = Class (tthread)

Protected

Procedure execute; override;

End;

 

VaR

Dllform: tdllform;

 

Implementation

 

{$ R *. DFM}

 

Procedure tdllthread. Execute;

VaR

Count: integer;

TP: tthreadprocedure;

Begin

Count: = 0;

While true do

Begin

Try

Sendmessage (dllform. Handle, wm_user + 100, INTEGER (

@ Procedure

Begin

Showmessage (inttostr (count ));

Count: = count + 2000;

End), 0

);

 

// TP: = procedure

// Begin

// Showmessage (inttostr (count ));

// Count: = count + 2000;

// End;

// Sendmessage (dllform. Handle, wm_user + 100, INTEGER (@ TP), 0 );

Except

// Ignore Error

End;

 

Sleep (2000 );

End;

End;

 

Procedure opendllwindow (amainhandle: integer); stdcall;

Begin

If dllform = nil then

Dllform: = tdllform. Create (application );

 

// Copy to the main program

// Application. Handle: = amainhandle;

// Dllform. showmodal;

Dllform. show;

End;

Exports opendllwindow;

 

 

Procedure tdllform. formshow (Sender: tobject );

VaR

Dllthread: tdllthread;

Begin

Dllthread: = tdllthread. Create (false );

End;

 

Procedure tdllform. wmrefreshform (var msg: tmessage );

Begin

If msg. MSG = wm_user + 100 then

Begin

Tthreadprocedure (pointer (msg. wparam). Invoke;

End;

End;

 

End.

 

If the tdllthread. Execute method is changed

Procedure tdllthread. Execute;

VaR

Count: integer;

TP: tthreadprocedure;

Begin

Count: = 0;

While true do

Begin

Try

TP: = procedure

Begin

Showmessage (inttostr (count ));

Count: = count + 2000;

End;

Sendmessage (dllform. Handle, wm_user + 100, INTEGER (@ TP), 0 );

Except

// Ignore Error

End;

Sleep (2000 );

End;

End;

The tdllform. wmrefreshform method should be changed:

Procedure tdllform. wmrefreshform (var msg: tmessage );

Begin

If msg. MSG = wm_user + 100 then

Begin

Tthreadprocedure (pointer (msg. wparam) ^). Invoke;

End;

End;

Note This.

In this way, we can achieve the same effect of synchronize with just a slight modification in the DLL program, and enjoy the convenience of using the anonymous method. The above code is debugged in delphi2010, I would like to share with you some suggestions on the shortcomings.

Author: Zhang Hao

2010-7-30

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.