Образец простой темы Delphi
Я новичок в этом деле Threading в Delphi. поэтому я пытаюсь сделать простой запрос, который немного вызывает вызов для базы данных и занимает немного времени, поэтому я хочу предупредить пользователя о том, что есть фоновый процесс и вы должны быть терпеливыми.
Я попробовал много образцов, но никто из них не работает для меня. Пожалуйста, может ли кто-нибудь показать мне простой пример, который мог бы работать?
Я знаю, что я должен объявить тип TThread, с Create и Override Execute... и т.д., но с тех пор я потерялся...
Использование Delphi 7, SQL Server 2005 и ADO, Windows XP sp3.-
Спасибо.
Ответы
Ответ 1
Вы можете найти множество примеров в сети потоков. Единственная особенность, если вы используете ADO-соединения внутри Thread, заключается в том, что вы не можете использовать одно и то же соединение.
Каждый поток должен создавать свое собственное соединение, в противном случае они равны (должны следовать тем же правилам, что и любой другой поток.)
Образец, который я использовал, следующий:
TADOSQLThread = class(TThread)
private
FADOQ: TADOQuery; // Internal query
FSQL: string; // SQL To execute
FID: integer; // Internal ID
public
constructor Create(CreateSuspended:Boolean; AConnString:String;
ASQL:string; IDThread:integer);
destructor Destroy; override;
procedure Execute(); override;
property ID:integer read FID write FID;
property SQL:string read FSQL write FSQL;
property ADOQ:TADOQuery read FADOQ write FADOQ;
end;
Конструктор Create переопределяется и выглядит следующим образом:
constructor TADOSQLThread.Create(CreateSuspended:Boolean; AConnString:String;
ASQL:string; IDThread:integer);
begin
inherited Create(CreateSuspended);
// ini
Self.FreeOnTerminate := False;
// Create the Query
FADOQ := TAdoquery.Create(nil);
// assign connections
FADOQ.ConnectionString := AConnString;
FADOQ.SQL.Add(ASQL);
Self.FID := IDThread;
Self.FSQL:= ASQL;
end;
И метод execute очень прост:
procedure TADOSQLThread.Execute();
begin
inherited;
try
// Ejecutar la consulta
Self.FADOQ.Open;
except
// Error al ejecutar
...Error treattement
end;
end;
Чтобы начать и создать поток, вы можете использовать код, похожий на этот:
//crear el Thread
th := TADOSQLThread.Create(True, mmConnection.Lines.Text, ASQL, AId);
// internal for me (for controled the number of active threads and limete it)
inc(numThreads);
// evento finalizacion
th.OnTerminate := TerminateThread;
// Ejecutarlo
th.Resume;
Я создал метод TerminateThread, который получает контроль над потоками, когда они заканчиваются. Единственное отличие от других потоков - проблема соединения. Вы должны создать новое соединение в каждом потоке, Он не может использовать одни и те же ADOConnections с другими.
Я надеюсь, что этот пример будет полезен для вас.
Привет
Ответ 2
Yup, вы объявляете новый тип, который наследуется от TThread:
TMyWorkerThread = class(TThread)
end;
Затем вы добавляете переопределение функции для Execute():
TMyWorkerThread = class(TThread)
public
procedure Execute; override;
end;
Эта процедура будет вызываться при запуске потока. Он будет выполнен параллельно с вашей основной программой. Пусть написано.
procedure TMyWorkerThread.Execute;
begin
//Here we do work
DoSomeWork();
DoMoreWork();
//When we exit the procedure, the thread ends.
//So we don't exit until we're done.
end;
Как это использовать? Предположим, вы хотите начать работу, когда пользователь нажимает кнопку. Вы пишете обработчик OnClick:
procedure TMainForm.Button1Click(Sender: TObject);
begin
TMyWorkerThread.Create(false);
end;
Что это. После того, как пользователь нажмет кнопку, ваш поток начнется и продолжит выполнение того, что вы написали в Execute. Если пользователь снова нажмет кнопку, начнется другой поток, а затем другой - по одному щелчку. Все они будут работать параллельно, каждый из которых выполняет все, что написано в Execute(), а затем заканчивается.
Скажем, вы хотите проверить, закончилась ли работа. Для этого вам нужно будет где-то хранить ссылку на ваш поток:
TMainForm = class(TForm)
{...skipped...}
public
MyWorkerThread: TThread;
end;
procedure TMainForm.Button1Click(Sender: TObject);
begin
//This time we make sure only one thread can be started.
//If one thread have been started already, we don't start another.
if MyWorkerThread<>nil then
raise Exception.Create('One thread have already been started!');
MyWorkerThread := TMyWorkerThread.Create(false);
end;
procedure TMainForm.Button2Click(Sender: TObject);
begin
//If the work is not over yet, we display message informing the user we're still working
if (MyWorkerThread<>nil) and (WaitForSingleObject(MyWorkerThread.Handle, 0)<>WAIT_OBJECT_0) then
MessageBox(Self.Handle, pchar("The work is not yet done!"), pchar("Still running"), MB_OK);
end;
Как вы видите, мы проверяем, работает ли поток, вызывая функцию Windows под названием WaitForSingleObject. Эта функция ждет, пока поток не будет выполнен, или истечет время ожидания, и когда мы укажем тайм-аут 0, он сразу же появится, если поток еще не закончился.