Это совсем не способ использования BeginThread
.Эта функция ожидает указатель на функцию, которая принимает один параметр, но функция, которую вы пытаетесь вызвать, хочет четыре.Единственный параметр, который вы указываете BeginThread
для передачи в потоковую процедуру, - это строка, но вы, очевидно, надеетесь, что какое-то волшебство превратит эту строку символов в значения, которые содержат эти переменные.
Это не так, как работает Delphi, и даже для языков, которые могут делать что-то подобное, обычно не рекомендуется на самом деле делать это.
Для передачи нескольких параметровна BeginThread
, определите запись со всеми необходимыми значениями, а также определите указатель записи:
type
PCompareFilesParams = ^TCompareFilesParams;
TCompareFilesParams = record
Edit3Text,
Edit4Text: string;
Grid: TStringGrid;
Op: Integer;
end;
Измените CompareFiles
, чтобы принять указатель на эту запись:
function CompareFiles(Params: PCompareFilesParams): Integer;
Чтобы запустить поток, вам нужно выделить экземпляр этой записи и заполнить ее поля:
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
так, чтобы запись освободилась перед потоком.прекращается:
function CompareFiles(Params: PCompareFilesParams): Integer;
begin
try
// <Normal implementation goes here.>
finally
Dispose(Params);
end;
end;
Вы можете сделать все это намного проще, если просто используете TThread
.Вы можете сделать так, чтобы ваш класс-потомок имел столько параметров, сколько вы хотите в его конструкторе, так что вам не придется возиться с динамическим размещением и освобождением специальной записи.
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;
Вместо вызова BeginThread
, вы просто создаете экземпляр класса и запускаете его:
var
ThreadRef: TThread;
ThreadRef := TCompareFilesThread.Create(Edit3.Text, Edit4.Text, StringGrid2, Op);
Существует еще кое-что для использования потоков, например, знание, когда поток завершил работу, но я думаю, у вас достаточно для начала работы.Последнее, что следует остерегаться, это то, что TStringGrid
является элементом управления VCL.Вы не должны ничего делать с ним из этой новой темы, которую вы создаете (независимо от того, как вы ее создали).Все, что вы делаете с контролем сетки, должно быть сделано из основного потока.Используйте TThread.Synchronize
и TThread.Queue
, чтобы перенести любые операции VCL в основной поток.Поток сравнения файлов будет ожидать завершения синхронизированной операции, но будет продолжать работу, не дожидаясь завершения операции в очереди.