Reprint: In case of a blog
Multithreading should be a basic skill for programmers, but the foundation is a bit difficult for me (at least yesterday).
The beginning should be a voluminous text, but I still advocate to do it first, in the attempt to understand.
Try this first.
Procedure Tform1.button1click (sender:tobject); var i:integer;begin for i:= 0 to 500000 do begin Canvas.textout (Ten, IntToStr (i)); End;end;
When the above program is running, our form is basically "dead", you can try to drag the form while the program is running.
Delphi provides us with an easy way (application.processmessages) to solve this problem
Procedure Tform1.button1click (sender:tobject); var i:integer;begin for i:= 0 to 500000 do begin Canvas.textout (Ten, IntToStr (i)); Application.processmessages; End;end;
This application.processmessages is typically used in more time-consuming loops, and it examines and processes other messages in the message queue
But this is not much of a thread, for example: When you drag a form in the run, the loop pauses
Before using multithreading, let's start by simply modifying the program
function Myfun:integer;var i:integer;begin for i:= 0 to 500000 do begin Form1.Canvas.Lock; Form1.Canvas.TextOut (Ten, IntToStr (i)); Form1.unlock; End; result:= 0;end;procedure Tform1.button1click (sender:tobject); begin Myfun;end;
To count the changes in the above program:
1. This is not multi-threaded at first, it will leave the form "dead" for a while
2. Write the execution code in a function, but this function does not belong to the TForm1 method, so the use of the canvas must be crowned with a name (FORM1)
3. Since it is a function, (whether or not necessary) should have a return value
4.5,000,001 times Lock and unlock are used
Canvas.lock like to say: canvas (drawing surface) is busy, others want to use canvas and so on
Canvas.unlock: Ran out, unlocked
Using lock and unlock in canvas is a good habit, but it doesn't matter if you don't use multithreading, but it's not guaranteed that the program will be extended to multi-threaded. We are now learning Multi-threading, of course, should use
There are two ways to use multithreading in Delphi: Calling the API, using the TThread class.
The code for using the API is much simpler
function Myfun (p:pointer): Integer; Stdcall;var I:integer;begin for i:=0 to 50000 do begin Form1.Canvas.Lock; Form1.Canvas.TextOut (Ten, IntToStr (i)); Form1.Canvas.UnLock; End; result:= 0;end;procedure Tform1.button1click (sender:tobject); var id:thandle;begin CreateThread (nil, 0, @ Myfun, nil, 0, ID); end;
Code Analysis:
CreateThread a thread, calculate the original main thread, so that the program has two threads, is the standard multi-threaded
The third parameter of the CreateThread is the function pointer, which executes immediately after the new thread is established, and the system destroys the thread to end the multithreaded story by executing the function.
CreateThread the function to be used is system level, cannot be a method of a class (for example: TForm1), and has strict formatting (parameters, return value) requirements, whether you need to be in the form of a temporary
Because it is a system-level call, and the Stdcall,stdcall is the coordinate parameter order, although there is only one parameter there is no order, but this is the Convention to use system functions
CreateThread also needs a var parameter to receive the ID of the new thread, although it is temporarily useless, but this is also the format; love him.
This is the simplest multi-thread that comes out, let's use the TThread class to implement a
Type tmythread=class (tthread) protected procedure Execute; override; End;procedure tmythread.execute;var i:integer;begin freeonterminate:= True; This allows the thread to complete and then release the for i:= 0 to 500000 do begin Form1.Canvas.Lock; Form1.Canvas.TextOut (Ten, IntToStr (i)); Form1.canvas,unlock; End;end;procedure Tform1.button1click (sender:tobject); begin Tmythread.create (False); end;
The TThread class has an abstract method (Execute), which is an abstract class that can only be inherited by an abstract class, with the inheritance of Tmythread
Inheriting TThread is mainly to implement the abstract method execute (write our code inside), after our Tmythread instantiation, first executes the code in the Execute method
As usual, we usually instantiate this.
Procedure Tform1.button1click (sender:tobject); var mythread:tmythread;begin mythread:= tmythread.create (False); end;
Because the mythread variable is useless here (and the compiler has hints), it is better to write Tmythread.create (False) directly;
We can also easily solve a problem if: Tmythread.create (True)?
This will not invoke execute immediately after the thread is created, and can then execute the thread with the resume method when needed, such as
Procedure Tform1.button1click (sender:tobject); var mythread:tmythread;begin mythread:= tmythread.create ( True); Mythread.resume;end;
can be simplified to
Procedure Tform1.button1click (sender:tobject); begin with tmythread.create (True) do resume;end;
When using the TThread class, Delphi has provided the template, using the IDE to write code is very convenient, I rewrite the record for everyone to see:
Ctrl+j, Shift+ctrl+c, ctrl+alt+p were used during the
Important Corrections and additions
In the case of the TThread class, there should be this sentence freeonterminate:= True; (originally omitted, the code is added, but the animation is not added)
First say what it means:
Class Create will have free
But TThread (subclass) is special, and many times we are not sure when the new thread is finished (that is, when it should be released).
If the thread finishes executing itself and knows to release it, TThread gives a Boolean attribute Freeonterminate, and if true, the thread will automatically release when it finishes executing.
How could I have overlooked such an important question? There are two reasons:
1, I have been in the pursuit of the most refined code;
2. I have more than one book on hand that says: The default value of Freeonterminate is True ( Error!), after implementation, should be False, at least in Delphi 2007 and 2009 is the case; Perhaps a previous version is not the same as it is now. (But some blogs and books say the default value is True, but not the problem, if you need to use it later, whether you want to use TRUE or false, or all of your own explicit assignment, this will not exist above the problem )
Delphi multithreaded Programming (1)--start with the first