Простой демонстрационный Delphi потока

Я являюсь новым с этим материалом Поточной обработки в Delphi. таким образом я пытаюсь подать заявку простого запроса, которые делают немного призыва для базы данных и занимают немного времени, таким образом, я хочу предупредить пользователя, что существует фоновый процесс и должен быть терпеливым.

Я попробовал много образцов, но ни один из них не работает на меня, кто-то мог показать мне простую выборку, которая могла работать?

Я знаю, что должен Объявить, что Тип TThread, с Создают, и Переопределение Выполняются... и т.д. но начиная с этого я потерян...

Используя Delphi 7, SQL Server 2005 и ADO, Windows XP sp3.-

Спасибо.

29
задан Jose M. Vilomar 10 August 2010 в 16:22
поделиться

2 ответа

Вы можете найти множество примеров в сети потоков. Единственная особенность, если вы используете соединения ADO внутри потока, заключается в том, что вы не можете использовать одно и то же соединение.
Каждый поток должен создать свое собственное соединение , в противном случае они равны (должны следовать тем же правилам, что и любой другой поток).

Пример, который я использовал, следующий:

  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;

И метод выполнения очень прост:

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 , который получить контроль над потоками, когда они закончат. Единственное отличие от других потоков - проблема с подключением. Вы должны создать новое соединение в каждом потоке, он не может использовать одни и те же соединения ADOC с другими.
Надеюсь, этот пример будет вам полезен.

С уважением

33
ответ дан 28 November 2019 в 00:49
поделиться

Ага, вы объявляете новый тип, который наследуется от 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, он просто существует немедленно, если поток еще не завершен.

53
ответ дан 28 November 2019 в 00:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: