Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 25.01.2014, 18:01   #1
bilibian
Форумчанин
 
Регистрация: 21.01.2014
Сообщений: 389
По умолчанию Delphi Завершение потока

Привет

Нужно, чтобы при нажатии на кнопку "Остановить" поток завершался и выполняемый скрипт останавливался.

Создаю и завершаю поток так:
Код:
procedure TForm1.Button1Click(Sender: TObject);
  var Th:TThread;
begin
  if button1.Tag=0 then begin
    button1.Tag:=1;
    button1.Caption:='Остановить';
    Th:=Th.Create(true);
    Th.FreeOnTerminate:=true;
    Th.Resume;
    Th.Priority:=tpNormal;
  end else begin
    button1.Tag:=0;
    button1.Caption:='Начать';
    Th.Terminate;
  end;
end;
При попытке завершить поток, то есть вызвать Th.Terminate выскакивает ошибка "cannot terminate an externally created thread" и ничего не останавливается. Как быть?
bilibian вне форума Ответить с цитированием
Старый 25.01.2014, 18:07   #2
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,351
По умолчанию

Попробуйте сделать переменную Th глобальной.
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA на форуме Ответить с цитированием
Старый 25.01.2014, 18:21   #3
northener
ПШП
Участник клуба
 
Регистрация: 15.07.2013
Сообщений: 1,896
По умолчанию

Цитата:
Th:=Th.Create(true);
Что это такое?
northener вне форума Ответить с цитированием
Старый 25.01.2014, 18:30   #4
bilibian
Форумчанин
 
Регистрация: 21.01.2014
Сообщений: 389
По умолчанию

Цитата:
Сообщение от BDA Посмотреть сообщение
Попробуйте сделать переменную Th глобальной.
Спасибо, помогло!
bilibian вне форума Ответить с цитированием
Старый 25.01.2014, 18:30   #5
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,351
По умолчанию

Цитата:
Сообщение от northener Посмотреть сообщение
Что это такое?
Точно
Кстати, TThread - абстрактный класс, вроде как, то есть сначала нужно создать класс потомок, а потом уж создавать его экземпляр.
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA на форуме Ответить с цитированием
Старый 25.01.2014, 18:31   #6
bilibian
Форумчанин
 
Регистрация: 21.01.2014
Сообщений: 389
По умолчанию

Цитата:
Сообщение от northener Посмотреть сообщение
Что это такое?
Я сделал так:

1. В самом потоке:
Код:
Th = class(TThread);
2. В основном потоке формы объявил глобальной:
Код:
var T:Th;
3. И на самой кнопке:
Код:
T:=Th.Create(True);

Последний раз редактировалось bilibian; 25.01.2014 в 18:37.
bilibian вне форума Ответить с цитированием
Старый 25.01.2014, 18:52   #7
Shouldercannon
Участник клуба Подтвердите свой е-майл
 
Аватар для Shouldercannon
 
Регистрация: 26.01.2008
Сообщений: 1,897
По умолчанию

Код:
unit frm_Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TFormMain = class(TForm)
    BStart2: TButton;
    BCheck2: TButton;
    procedure BStart2Click(Sender: TObject);
    procedure BCheck2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
  TMyThread2 = class(TThread)
  private
    { Private declarations }
    i: Integer;
  protected
    procedure Execute; override;
    procedure SyncProc;
  public
  end;

var
  FormMain: TFormMain;
  MyThread2: TMyThread2;

implementation

{$R *.dfm}

procedure TFormMain.BStart2Click(Sender: TObject);
begin
  if BStart2.Tag = 0 then
  begin
    BStart2.Tag := 1;
    BStart2.Caption := 'Стоп';

    MyThread2 := TMyThread2.Create(True); // После создания поток остановлен
    MyThread2.FreeOnTerminate := True; // После завершения работы поток "не умрёт" сам
    MyThread2.Resume; // Запуск потока
  end
  else
  begin
    BStart2.Tag := 0;
    BStart2.Caption := 'Старт';
    // Поток не прекращает свою работу
    // НЕ УБИВАЕТ поток, а просто выставляет свойство Terminated в True
    // Поток сам должен следить (в теле Execute) за тем, когда должен умереть
    // Жёстко уничтожить поток можно с помощью TerminateThread, но делать этого нельзя, потому как утечки памяти как минимум... ну и прочие неприятности
    MyThread2.Terminate;
  end;
end;

procedure TMyThread2.Execute;
var
  i2: Integer;
begin
  for i2 := 0 to 60 do
  begin
    if Self.Terminated then Exit; // Если главный поток приказал - умираем

    if i2 > 61 then Break;
    Sleep(100);
    i := i2;
    Synchronize(SyncProc);
  end;

  Terminate;
end;

procedure TMyThread2.SyncProc;
begin
  FormMain.Caption := IntToStr(i);
end;

procedure TFormMain.BCheck2Click(Sender: TObject);
begin
  // Проверка на существование потока
  if MyThread2 <> nil then
  begin
    // Если поток умирает "мирно", штатно завершив работу
    if MyThread2.Terminated then ShowMessage('Поток "MyThread2" не работает') else ShowMessage('Поток "MyThread2" работает');
  end else ShowMessage('Поток "MyThread2" не создан');
end;

end.
Shouldercannon вне форума Ответить с цитированием
Старый 26.01.2014, 06:40   #8
bilibian
Форумчанин
 
Регистрация: 21.01.2014
Сообщений: 389
По умолчанию

В общем сделал так:

В отдельный поток подключил главный поток с данными о кнопках которые располагаются на форме:

Код:
type
  TFormMain = class(TForm)
    Button1: TButton;
    Button8: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button8Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
  Th = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
  end;

var T:Th;
    FormMain:TFormMain;

implementation

Код:
procedure Th.Execute;
begin

   Пишем основной код, который будет выполняться при нажатии на кнопку Старт

end;

Далее, пишу код для кнопки "Старт":

Код:
procedure TFormMain.Button1Click(Sender: TObject);
begin
  if button1.Tag=0 then
  begin
    button1.Tag:=1;
    button1.Caption:='Остановить';
    T:=Th.Create(true);
    T.FreeOnTerminate:=true;
    T.Resume;
    T.Priority:=tpNormal;
  end
  else
  begin
    button1.Tag:=0;
    button1.Caption:='Старт';
    T.Terminate;
  end;
end;

В итоге при нажатии на кнопку Старт в проге, вообще ничего не происходит.

Последний раз редактировалось bilibian; 26.01.2014 в 07:08.
bilibian вне форума Ответить с цитированием
Старый 26.01.2014, 10:40   #9
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Отладчиком конечно же не проходил?
Тогда стелепатирую - код "Пишем основной код, который будет выполняться при нажатии на кнопку Старт" выполнился незаметно.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 26.01.2014, 11:36   #10
bilibian
Форумчанин
 
Регистрация: 21.01.2014
Сообщений: 389
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
код выполнился незаметно.
Это исключено! Ведь даже Caption кнопки не поменялся, хотя это условие должно быть выполнено еще до открытия потока. Соответственно между кнопкой которая находится на форме и кодом который для нее прописан в другом потоке нет связи!
bilibian вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Грамотное завершение потока, если поток на паузе winhttp Общие вопросы .NET 3 11.01.2013 12:55
Завершение потока coNsept Общие вопросы C/C++ 3 20.06.2012 19:42
Принудительное завершение потока не работает :(! TEED! Работа с сетью в Delphi 3 06.06.2012 14:34
C# BackgroundWorker - завершение работы потока Lastsummer Помощь студентам 2 16.03.2011 18:04
Как отследить завершение выполнения потока TThread? Трик Общие вопросы Delphi 3 24.10.2007 14:55