BeginThread Structure - Delphi

Now I have an almost complete application, and the next function I want to implement is streaming. I decided to go with BeginThread (), although I know about TThread in delphi. The problem I am facing is the structure of the BeginThread () call. Usually the line in the program that will call the function that I want to do is

CompareFiles(form1.Edit3.Text,Form1.Edit4.Text,Form1.StringGrid2,op); 

op is an integer.

The line that I turned off to create a stream from it,

 BeginThread(nil,0,CompareFiles,Addr('form1.Edit3.Text,Form1.Edit4.Text,Form1.StringGrid2,op'),0,x); 

From a small amount of information, I can find how to actually use BeginThread (), it should be a wonderful call, however, when compiling everything I get, these are errors related to the calculation regarding the structure of my arguments to the BeginThread () instruction.

EDIT INFORMATION.

The current procedure that calls CompareFiles,

 procedure TForm1.Panel29Click(Sender: TObject); var op,x : integer; begin if (Form1.Edit3.Text <> '') AND (Form1.Edit4.Text <> '') then begin op := 3; if RadioButton7.Checked = True then op := 0; if RadioButton3.Checked = True then op := 1; if RadioButton4.Checked = True then op := 2; if RadioButton5.Checked = True then op := 3; if RadioButton6.Checked = True then op := 4; CompareFiles(form1.Edit3.Text,Form1.Edit4.Text,Form1.StringGrid2,op); end; end; 

If I used TThread, as suggested by several people, and as Rob showed below, I am confused about how a) I passed op, Edit3 / 4.Text and StringGrid2 to CompareFiles. Guessing from the TThread example, I saw that I decided to replace the code above with TCompareFilesThread.Execute and put the current code from Panel29Click into TCompareFilesThread.Create , and then add

 FEdit3Text := Edit3Text; FEdit4Text := Edit4Text; FGrid := Grid; 

to that

 FEdit3Text := Form1.Edit3.Text; FEdit4Text := Form1.Edit4.Text; FGrid := Form1.StringGrid2; 

But I have this feeling of disgust, which is completely irrelevant.

+5
multithreading delphi
Jan 25 2018-11-11T00:
source share
1 answer

This is not a way to use BeginThread . This function expects a pointer to a function that takes one parameter, but the function you are trying to call requires four. One parameter that you pass BeginThread to send to the thread procedure is the string, but you obviously hope that some kind of magic will turn this string of characters into the values โ€‹โ€‹that these variables contain.

This is not how Delphi works, and even for languages โ€‹โ€‹that can do something similar, it is usually not recommended to do this.

To pass several parameters to BeginThread , define a record with all the necessary values, and also define a record pointer:

 type PCompareFilesParams = ^TCompareFilesParams; TCompareFilesParams = record Edit3Text, Edit4Text: string; Grid: TStringGrid; Op: Integer; end; 

Modify CompareFiles to accept a pointer to this entry:

 function CompareFiles(Params: PCompareFilesParams): Integer; 

To start the stream, you need to select an instance of this record and fill in its fields:

 var Params: PCompareFilesParams; begin New(Params); Params.Edit3Text := Edit3.Text; Params.Edit4Text := Edit4.Text; Params.Grid := StringGrid2; Params.Op := op; BeginThread(nil, 0, @CompareFiles, Params, 0, x); 

CompareFiles so that the record is freed before the stream completes:

 function CompareFiles(Params: PCompareFilesParams): Integer; begin try // <Normal implementation goes here.> finally Dispose(Params); end; end; 

You can make it all a lot easier if you just use TThread . You can make your descendant class have as many parameters as you want in its constructor, so you donโ€™t have to bother with dynamic allocation and freeing up a special record.

 type TCompareFilesThread = class(TThread) private FEdit3Text, FEdit4Text: string; FGrid: TStringGrid; FOp: Integer; procedure Execute; override; public constructor Create(const Edit3Text, Edit4Text: string; Grid: TStringGrid; Op: Integer); property ReturnValue; end; constructor TCompareFilesThread.Create; begin inherited Create(False); FEdit3Text := Edit3Text; FEdit4Text := Edit4Text; FGrid := Grid; FOp := Op; end; procedure TCompareFilesThread.Execute; begin ReturnValue := CompareFiles(FEdit3Text, FEdit4Text, FGrid, FOp); end; 

Instead of calling BeginThread you simply create an instance of the class and run it:

 var ThreadRef: TThread; ThreadRef := TCompareFilesThread.Create(Edit3.Text, Edit4.Text, StringGrid2, Op); 

There is more to use threads, for example, knowing when the thread finished working, but I think you have enough to get started. The last thing to be wary of is that TStringGrid is a VCL control. You should not do anything with it from this new thread that you create (no matter how you create it). Everything you do with grid control should be done from the main thread. Use TThread.Synchronize and TThread.Queue to change any VCL operations to the main thread. Your file compare thread will wait for the synchronized operation to complete, but it will continue to work without waiting for the queue to complete.

+14
Jan 25 2018-11-11T00:
source share



All Articles