Why is the corresponding handle still in the active state after waitformultipleobjects returns? Delphi/Windows SDK/API
Http://www.delphi2007.net/DelphiAPI/html/delphi_20061107172543284.html
I wrote an example of using the waitformultipleobjects synchronization thread. There are three memo on the form, one mutex array variable corresponding to one memo, and the scheduling thread is created in the main thread, in the scheduling thread, waitformultipleobjects is used to get the currently idle mutex. Then, I will know which memo is idle, create a working thread, and write data to the corresponding memo in the working thread,
The problem is that after waitformultipleobjects returns, it always returns 0. After waitformultipleobjects returns, the first element of the mutex array is in the not-fired state, if you call waitformultipleobjects again, no zero should be returned.
.
Below is Code Please help me see where the problem is
Unit unit1;
Interface
Uses
Windows, messages, sysutils, variants, classes, graphics, controls, forms,
Dialogs, stdctrls;
Type
Tform1 = Class (tform)
Button1: tbutton;
Memo1: tmemo;
Memo2: tmemo;
Memo3: tmemo;
Procedure formcreate (Sender: tobject );
Procedure formdestroy (Sender: tobject );
Procedure button1click (Sender: tobject );
Private
{Private Declarations}
Public
{Public declarations}
End;
Tdispthd = Class (tthread)
Private
Protected
Procedure execute; override;
Public
Constructor create (MoNE: tmemo; mtwo: tmemo; mthree: tmemo );
End;
Tworker = Class (tthread)
Private
Fmemo: tmemo;
Ftid: integer;
Findex: integer;
Protected
Procedure execute; override;
Procedure updatememo;
Public
Constructor create (index, ID: integer; memo: tmemo );
End;
VaR
Form1: tform1;
Connmutexuse: array [0 .. 2] of thandle;
Memoarr: array [0 .. 2] of tmemo;
Procedure getidlememo (var id: integer );
Implementation
{$ R *. DFM}
Procedure getidlememo (var id: integer );
VaR
Waitres: integer;
Begin
Waitres: = waitformultipleobjects (3, @ connmutexuse, false, infinite );
ID: = waitres-wait_object_0;
// Waitres: = waitforsingleobject (connmutexuse [ID], 10 );
// If waitres = wait_object_0 then
// Raise exception. Create ('bad, I catch it ');
If (ID <0) or (ID> 2) then
Raise exception. Create ('getidle error ');
End;
Constructor tdispthd. Create (MoNE: tmemo; mtwo: tmemo; mthree: tmemo );
Begin
Memoarr [0]: = mone;
Memoarr [1]: = mtwo;
Memoarr [2]: = mthree;
Inherited create (false );
End;
Procedure tdispthd. Execute;
VaR
ID, I, waitres: integer;
Begin
Freeonterminate: = true;
I: = 0;
While true do
Begin
Getidlememo (ID );
// Waitres: = waitformultipleobjects (3, @ connmutexuse, false, infinite );
// ID: = waitres-wait_object_0;
// Waitres: = waitforsingleobject (connmutexuse [ID], 10 );
// If waitres = wait_object_0 then
// Raise exception. Create ('bad, I catch it ');
// If (ID <0) or (ID> 2) then
// Raise exception. Create ('getidle error ');
Tworker. Create (I, ID, memoarr [ID]);
Sleep (2000 );
INC (I );
End;
End;
Procedure tform1.formcreate (Sender: tobject );
VaR
I: integer;
Begin
For I: = 0 to 2 do
Connmutexuse [I]: = createmutex (nil, false, nil );
End;
Procedure tform1.formdestroy (Sender: tobject );
VaR
I: integer;
Begin
For I: = 0 to 2 do
Closehandle (connmutexuse [I]);
End;
Constructor tworker. Create (index, ID: integer; memo: tmemo );
Begin
Fmemo: = memo;
Ftid: = ID;
Findex: = index;
Freeonterminate: = true;
Inherited create (false );
End;
Procedure tworker. Execute;
VaR
Waitres: integer;
Begin
Try
Synchronize (updatememo );
// Waitres: = waitforsingleobject (connmutexuse [ftid], 10 );
// If waitres = wait_object_0 then
// Raise exception. Create ('bad, I catch it ');
Sleep (50000 );
Finally
Releasemutex (connmutexuse [ftid]);
End;
End;
Procedure tworker. updatememo;
Begin
Fmemo. lines. Add (inttostr (ftid) + ':' + inttostr (findex ));
End;
Procedure tform1.button1click (Sender: tobject );
Begin
Tdispthd. Create (memo1, memo2, memo3 );
End;
End.
Help you top
A thread with a mutex will not be locked. It can be reinjected all the time and will only lock other threads.
The internal count of mutex is increased by waitforsingleobject, and the internal count of mutex is decreased by releasemutex.
Upstairs positive solution ~~~~
Because the getidlememo function of LZ is always called by the thread tdispthd, it can be re-imported into waitformultiojbect. Run the getidlememo function in tworker. Execute;
As shown below, I changed the code.
Unit unit1;
Interface
Uses
Windows, messages, sysutils, variants, classes, graphics, controls, forms,
Dialogs, stdctrls;
Type
Tform1 = Class (tform)
Memo1: tmemo;
Memo2: tmemo;
Memo3: tmemo;
Button1: tbutton;
Procedure formcreate (Sender: tobject );
Procedure formclose (Sender: tobject; var action: tcloseaction );
Procedure button1click (Sender: tobject );
Private
{Private Declarations}
Public
{Public declarations}
End;
Tdispthd = Class (tthread)
Private
Connmutexuse: array [0 .. 2] of thandle;
Protected
Procedure execute; override;
Public
Constructor create (MoNE: tmemo; mtwo: tmemo; mthree: tmemo );
End;
Tworker = Class (tthread)
Private
Fmemo: tmemo;
Ftid: integer;
Findex: integer;
Protected
Procedure execute; override;
Procedure updatememo;
Public
Constructor create (index, ID: integer; memo: tmemo); overload;
Constructor create (Index: integer); overload;
End;
VaR
Form1: tform1;
Connmutexuse: array [0 .. 2] of thandle;
Memoarr: array [0 .. 2] of tmemo;
Procedure getidlememo (var id: integer );
Implementation
{$ R *. DFM}
Procedure getidlememo (var id: integer );
VaR
Waitres: integer;
Begin
Waitres: = waitformultipleobjects (3, @ connmutexuse, false, infinite );
ID: = waitres-wait_object_0;
If (ID <0) or (ID> 2) then
Raise exception. Create ('getidle error ');
End;
{Tworker}
Constructor tworker. Create (index, ID: integer; memo: tmemo );
Begin
Fmemo: = memo;
Ftid: = ID;
Findex: = index;
Freeonterminate: = true;
Inherited create (false );
End;
Constructor tworker. Create (Index: integer); // Add a constructor.
Begin
Findex: = index;
Freeonterminate: = true;
Inherited create (false );
End;
Procedure tworker. Execute;
VaR
Waitres: integer;
Begin
Getidlememo (ftid );
Fmemo: = memoarr [ftid];
Try
Synchronize (updatememo );
Sleep (3500); // The time is short. It must be greater than 3*1000.
Finally
Releasemutex (connmutexuse [ftid]);
End;
End;
Procedure tworker. updatememo;
Begin
Fmemo. lines. Add (inttostr (ftid) + ':' + inttostr (findex ));
End;
{Tdispthd}
Constructor tdispthd. Create (MoNE, mtwo, mthree: tmemo );
Begin
Memoarr [0]: = mone;
Memoarr [1]: = mtwo;
Memoarr [2]: = mthree;
Inherited create (false );
End;
Procedure tdispthd. Execute;
VaR
ID, I, waitres: integer;
Begin
Freeonterminate: = true;
I: = 0;
While true do
Begin
// Getidlememo (ID );
// Tworker. Create (I, ID, memoarr [ID]);
Tworker. Create (I );
Sleep (1000); // short time
INC (I );
End;
End;
Procedure tform1.formcreate (Sender: tobject );
VaR
I: integer;
Begin
For I: = 0 to 2 do
Connmutexuse [I]: = createmutex (nil, false, nil );
End;
Procedure tform1.formclose (Sender: tobject; var action: tcloseaction );
VaR
I: integer;
Begin
For I: = 0 to 2 do
Closehandle (connmutexuse [I]);
End;
Procedure tform1.button1click (Sender: tobject );
Begin
Tdispthd. Create (memo1, memo2, memo3 );
End;
End.
Thank you for your help.