delphi threads teaching VII: multiple threads in space and time, the respective code specified stuffed into a space-time thread running

Reprinted from: https://www.cnblogs.com/lackey/p/6337357.html

VII: the plurality of threads in space and time, the respective code stuffed into a designated space-time thread run
   
To Ado, for example, a common method is to drag a AdoConnection on the window (or the DataModule),
Coupled with AdoQuery, DataSoure, DbGrid, etc., you can achieve access to the database.
In this way, it can be understood as the main thread to access the database in time and space.
If a particular query or update operation takes a long time, then the interface will be suspended animation.
 
1. Access database space and time in thread
 
In fact, the above mentioned this AdoConnection not only the main thread can only be accessed in space and time,
Also can be accessed in another multi-threaded space-time. But there is an important premise:
That is: any time, only one thread to access AdoConnection!
Can be multi-threaded space-time access, you can also access the main thread time and space, they can alternate access, but not both.
 
Therefore, we can define a thread DataThread time and space, time and space in the other threads need to access the database operation,
All stuffed into DataThread time and space. Specific approach is to design an interface DataThread as follows:
 
unit uJooThread;
interface
uses
  Classes, uFooThread;
type
 
  TJooThread = class(TFooThread)
  public
    procedure Synchronize(AProc: TThreadMethod);
  end;
 
implementation
 
{ TJooThread }
 
procedure TJooThread.Synchronize(AProc: TThreadMethod);
begin
  Akshechfrochintread (Afroc);
  // wait for a redesign AProc execution result.
end;
 
end.

  

 
This not only simplifies the operation of the other threads access the database, but also to avoid time-consuming operation because the database interface caused suspended animation.
In addition, if an abnormality occurs to access the database, and then operate again to re-Create AdoConnection this connection also be a thread,
It is not necessary to consider the issue has database operations. Such as: the need to access the database does not appear, AoConnection case is corrupted state.
In other words, use this thread, the operations were queuing to access the database.
 
Define a worker A, start the database taking parameters, and then calculated, and then the results to update the database.
If there are 10 threads A instances, the thread A accesses the database, just need access operations into DataThread can be.
 
A friend must be some doubt, why not assign a thread for each AdoConnection. Such programming will become easier.
First, the connection to the database will consume resources, the number of connections is capped.
Second, if the operation of each thread is produced AdoConnection access the same table.
Then the database itself at the lock, turn them into serial execution, it does not improve efficiency.
 
2. Multiple clients, while taking parameters from the database will be how?
 
Assuming that each client to obtain the parameters by a AdoStoredProcduce (stored procedures), we can in this stored procedure,
sp_getapplock added to the database (for example to MSSQL) to allow the client to obtain parameters in order. Update also empathy.
 
Thus, learning a multi-threaded lock can also be understood by extension lock the database.
 
The following is a detailed code, so far, this tutorial basically completed the task.
Call the method of this example do not write. If you read all the tutorials, you should write.
If you do not read, write, what significance does it have? Please brush up the basics of object-oriented.
Other tutorials later, are the basis of this multi-threading tutorial.
 
unit uJooThread;
interface
uses
  Classes, SyncObjs, uFooThread, uFooList;
type
  PSyncRec = ^TSyncRec;
  TSyncRec = record
    Method: TThreadMethod; // this is a class method
    Proc: TThreadProcedure; // this is an anonymous method
    // This example is only to write methods of the class. Anonymous method requires you overload yourself and Queue Sync
    Signle: TEvent;
    Queue: boolean;
  end;
 
  TSyncRecList = class (TFooList <PSyncRec>) // List for containing code for execution
  protected
    procedure FreeItem(Item: PSyncRec); override;
  end;
 
  TJooThread = class(TFooThread)
  private
    FSyncRecList: TSyncRecList;
    procedure Check;
  public
    constructor Create(ACanAccessCom: boolean);
    destructor Destroy; override;
    procedure Synchronize (AProc: TThreadMethod); // obstruction to AProc finished before returning.
    procedure Queue (AProc: TThreadMethod); // returns immediately after the stuffed thread.
  end;
  // This example is the integrated use of single speak in front of knowledge.
  // TEvent, FooThread, FooList, all were using.
  // and build a new thread function.
  // When I finished writing found, the system source code,
  // UI window function processing operation after receiving the message WM_NULL, almost exactly the same.
  // The difference is that, in the present embodiment is a space-time thread, the main thread system source code is temporal.
implementation
{ TJooThread }
procedure TJooThread.Check;
where
  p: PSyncRec;
begin
  FSyncRecList.Lock; // all the code to be executed, we are in this List.
  // This is the space-time thread, it can fetch and execute the code from the List.
  try
    p := nil;
    if FSyncRecList.Count> 0 then // List each taking first performed.
    begin
      p := FSyncRecList[0];
      FSyncRecList.Delete(0);
    end;
  finally
    FSyncRecList.Unlock;
  end;
 
  if Assigned(p) then
  begin
 
    if Assigned(p.Method) then
      p.Method
    else if Assigned(p.Proc) then
      p.Proc();
 
    if not p.Queue then // If it is blocked, set signal.
      p.Signle.SetEvent;
 
    Dispose (p);
 
    ExecProcInThread(Check);
  end;
end;
 
constructor TJooThread.Create(ACanAccessCom: boolean);
begin
  inherited;
  FSyncRecList := TSyncRecList.Create;
end;
 
destructor TJooThread.Destroy;
begin
  FSyncRecList.Free;
  inherited;
end;
 
procedure TJooThread.Queue(AProc: TThreadMethod);
where
  p: PSyncRec;
begin
  FSyncRecList.Lock;
  try
    new(p);
    FSyncRecList.Add(p);
    p.Method := AProc;
    p.Queue := true;
    ExecProcInThread(Check);
  finally
    FSyncRecList.Unlock;
  end;
end;
 
procedure TJooThread.Synchronize(AProc: TThreadMethod);
where
  p: PSyncRec;
  o: TEvent;
begin
  FSyncRecList.Lock;
  try
    new(p);
    FSyncRecList.Add(p);
    p.Method := AProc;
    o := TEvent.Create(nil, true, false, '');
    p.Signle: = O;
    p.Queue := false;
    ExecProcInThread (Check); // trigger thread starts
  finally
    FSyncRecList.Unlock;
  end;
  o.WaitFor; // wait AProc finished signal
  o.Free;
end;
 
{ TSyncRecList }
procedure TSyncRecList.FreeItem(Item: PSyncRec);
begin
  inherited;
  if Assigned(Item.Signle) then
    Item.Signle.Free;
  Dispose(Item);
end;
 
end.

  

Guess you like

Origin www.cnblogs.com/approx/p/11852351.html