|
#1
|
|||
|
|||
Класс и поток
Прошу помощи как начинающий.
Ниже выкладываю обобщенные фрагменты из программы. Есть класс TCSyn и поток MyThread. В потоке выполняется процедура VaChar. Скажу сразу программа компилируется без ошибок и выполняется. Но... Но когда запускается поток в процедуре VaChar при выполнении Count:= Count+1; происходит ошибка и процесс останавливается. Похоже, что поток не видит переменных описанных в классе TCSyn. Прошу подсказать как исправить это и что делал не правильно. Код:
TCSyn = class(TComponent) //TComponent Public inp : Tinp; FString : String; Сообщение Count : integer; Tek : Double; TimeTek : Double; Constructor Create(AOwner:TComponent);override; Destructor Destroy; override; procedure VaChar; Protected Private End; ------------------------------------- type MyThread=class(TThread) private{private declaration} pser: TCSyn; protected procedure execute;override; public end; var MyThr: MyThread; ------------------------------------------------------------------------- procedure MyThread.execute; var S: string; i:integer; begin Synchronize(pser.VaChar); end; ------------------------------------------------------------------------ procedure TCSyn.VaChar; var S:String; begin Count:= Count+1; end; |
#2
|
|||
|
|||
1. А тебе точно нужно класс "рожать" от TComponent? Тут я даже не знаю как оно будет работать в потоке, вроде проблем быть не должно, но я бы все-таки в потоке с визуальными компонентами не связывался.
2. А ты уверен, что происходит ошибка? Вообще, по твоему коду процедура потока выполняется 1 раз и потом поток завершается. 3. Ну и, надебсь, ты же создаешь экземпляр TCSyn в конструкторе потока? Просто не указал данный код в примере... |
#3
|
|||
|
|||
Цитата:
1 Класс рожать надо, хуже того он рожден до меня другим разработчиком, программа дорабатывается и переделывается мной не столь опытным. Хотелось бы ломать по минимуму. Поток работает, скажу больше, в примере не все выложено, но в процедуре execute предварительно читаются два сом порта, а дальнейшая обработка должна производится в VaChar используя данные класса. 2 Ошибка точно происходит и поток выполняется не один раз. 3 Да надо создать экземпляр TCSyn. pser := TCSyn.Create(nil); Вот только где? В процедуре execute? Или писать что-то новое? И как потом связать? Вообщем опыта мало, вопросов много. PS. Подскажите,пожалуйста, как пользоваться тегами. |
#4
|
|||
|
|||
1. Не факт, что предыдущий разраб был хорошим.
Тут вопрос не в том, надо ли "рожать" класс, а в том - от какого предка. Походу надо смотреть весь код, что бы понять, надо ли его рожать от TComponent или все-таки ничего из TComponent не используется и он нафиг не нужен и можно обойтись TObject. 2. Опять же, значит ты не предоставил правильный код. Или имеется в виду, что поток запускается несколько раз? Тут без некоторых важных частей кода не поймешь как оно устроенно. Предоставленный тобой пример может не отражать реальную структуру. Вообще, я бы для начала просто "завернул" бы весь код Execute в Try..Except и залогировал бы появляющуюся ошибку, что бы понять что же там происходит. 3. Я бы, навеоное, создавал его в конструкторе потока. Ну и в деструкторе уничтожал бы. 4. Засовывать ВСЮ обработку данных в Synchronize "не есть гут". Это блокирует основной поток приложения. Synchronize надо использовать только когда идет обращение к объектам главного потока. PS. Включи расширенный режим редактирования сообщения. Там есть готоыве кнопочки для вставки тегов. Вообще, тут в основном используется 2 тега - code и quote (в кв. скобках, закрывающий тег имеет слеш перед именем). |
#5
|
|||
|
|||
Кстати, не знаю какая ошибка у тебя вылетает... Сделал пример на основе твоего кода (пришлось кое-что добавить, что бы было красиво), но все работает:
Код:
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TCSyn = class; TMyThread = class; TForm1 = class(TForm) btStartThread: TButton; btReadCount: TButton; procedure FormCreate(Sender: TObject); procedure btStartThreadClick(Sender: TObject); procedure btReadCountClick(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } FMyThread : TMyThread; public { Public declarations } end; TCSyn = class(TComponent) public Count : integer; constructor Create(AOwner:TComponent); override; destructor Destroy; override; procedure VaChar; end; TMyThread = class(TThread) private pser: TCSyn; FDoWork : Boolean; protected procedure Execute; override; public constructor Create(CreateSuspended : Boolean); virtual; destructor Destroy; override; function GetCount : Integer; procedure DoWork; end; var Form1: TForm1; implementation {$R *.dfm} constructor TCSyn.Create(AOwner:TComponent); begin inherited; Count := 0; end; destructor TCSyn.Destroy; begin inherited; end; procedure TCSyn.VaChar; begin Count := Count + 1; end; constructor TMyThread.Create(CreateSuspended : Boolean); begin inherited Create(CreateSuspended); FDoWork := False; pser := TCSyn.Create(Nil); end; destructor TMyThread.Destroy; begin pser.Free; end; procedure TMyThread.Execute; begin While Not Terminated Do Begin If FDoWork Then Begin FDoWork := False; Synchronize(pser.VaChar); End; Sleep(100); End; end; function TMyThread.GetCount : Integer; begin Result := pser.Count; end; procedure TMyThread.DoWork; begin FDoWork := True; end; procedure TForm1.btReadCountClick(Sender: TObject); begin If Not Assigned(FMyThread) Then MessageDlg('Thread object is not created. Please click "Start Thread" button first',mtError,[mbOk],0) Else ShowMessage(Format('Count = %d',[FMyThread.GetCount])); end; procedure TForm1.btStartThreadClick(Sender: TObject); begin If Not Assigned(FMyThread) Then FMyThread := TMyThread.Create(False) Else FMyThread.DoWork; end; procedure TForm1.FormCreate(Sender: TObject); begin FMyThread := Nil; end; procedure TForm1.FormDestroy(Sender: TObject); begin If Assigned(FMyThread) Then Begin FMyThread.Terminate; FMyThread.WaitFor; FMyThread.Free; End; end; end. Да, для реального кода надо будет еще обложиться критическими секциями, что бы не получалось запустить обработку в потоке, если она уже идет. Или вообще лучше сделать очередь заданий, помещать новые задания туда, а поток сам будет от туда их забирать (опять же обложившись критическими секциями). Но в таком простом варианте все работает нормально. Никаких ошибок не вылетает. ЗЫ. Все делано на 10.2, но думаю, что на других версиях все будет ровно так же. Последний раз редактировалось lmikle, 03.08.2022 в 00:16. |
Этот пользователь сказал Спасибо lmikle за это полезное сообщение: | ||
arktik (20.08.2022)
|
#6
|
|||
|
|||
Спасибо за помощь, все работает! Благодарю Вас!
|
#7
|
|||
|
|||
Могу ли я здесь задать следующий вопрос, касательно СОМ порта или создать отдельную тему?
|
#8
|
|||
|
|||
Лучше, наверное, отдельную тему.
|