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

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

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

Восстановить пароль
Повторная активизация e-mail

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

Ответ
 
Опции темы Поиск в этой теме
Старый 14.06.2015, 15:07   #1
Antony41
Пользователь
 
Аватар для Antony41
 
Регистрация: 20.03.2009
Сообщений: 99
Вопрос

Нужен Ваш совет.
Немогу сообразить как правильно сделать.
Есть 1 дополнительный поток (второй это главный)
есть глобальная переменная опубликованная в главном потоке
Так вот как только её пытаешься изменить из доп. потока, вываливается AV
изменить я буду через PostMessage из доп. потока

Но дело в том что необходимо перед изменением этой переменной узнать её состояние. например так
Код:
if a=1 then
a:=2;
postmessage(handle, wm_change, Integer(a), 0);
Вы мне скажите можно ли проверять состояние глобальной переменной (которая опубликована в другом потоке) без средств синхронизации? тобишь использовать только чтение
или как правильно узнать состояние переменной из другого потока

P.S.
Немного не правильно пример привел
Код:
{ThreadUnit}
...
private
FA : Integer;


if MainUnit.A = 1 then
FA := 2;
postmessage(handle, wm_change, Integer(FA), 0); //ну или synchronize(DoChange)
Ну так как? или проверять состояние переменной тоже необходимо делать в Synchronize?

Последний раз редактировалось Stilet; 14.06.2015 в 17:11.
Antony41 вне форума Ответить с цитированием
Старый 14.06.2015, 16:46   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 19,042
По умолчанию

А чем синхронизация пугает? Выполнил postmessage, сообщение стало в очередь в основном потоке, пока суть да дело дошла наконец очередь до обработки его, то есть изменение значение. И в это время доп.поток нахально требует без всякой синхронизации это самое значение. Догадайся с трех раз что будет
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 14.06.2015, 17:11   #3
Antony41
Пользователь
 
Аватар для Antony41
 
Регистрация: 20.03.2009
Сообщений: 99
По умолчанию

Значит примерно так
Код:
{ThreadUnit}
...
private
FA : Integer;
procedure GetA;

procedure TThread.GetA;
begin
FA := MainUnit.A;
end;

procedure TThread.execute;
begin
Synchronize(GetA);
if FA = 1 then
begin
FA := 2;
postmessage(handle, wm_change, Integer(FA), 0); //ну или synchronize(DoChange)
end;
end;
Злой AV ушел спасибо!

Подскажите еще как можно изменить переменную объявленную в Thread1 из потока Thread2
если Thread1 иногда сам её изменяет или читает,
ведь Synchronize() это выполнение кода внутри главного потока

Последний раз редактировалось Stilet; 14.06.2015 в 18:17.
Antony41 вне форума Ответить с цитированием
Старый 14.06.2015, 18:13   #4
min@y™
Цифровой кот
Старожил
 
Аватар для min@y™
 
Регистрация: 29.08.2014
Сообщений: 7,656
По умолчанию

Цитата:
Подскажите еще как можно изменить переменную объявленную в Thread1 из потока Thread2
если Thread1 иногда сам её изменяет или читает,
читай про CriticalSection - критические секции - это как раз инструменты синхронизации между потоками для доступа к общим данным..
Расскажу я вам, дружочки, как выращивать грибочки: нужно в поле утром рано сдвинуть два куска урана...
min@y™ вне форума Ответить с цитированием
Старый 14.06.2015, 20:01   #5
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

Еще можно синхронизацию между потоками сделать с помощью Event.
Пример на ваших данных, поток без класса, можете для себя переделать, если потоки будут грузить процессор можете сделать в работе потока еще одно прерывание либо sleep либо еще event. Пока непонятно что вы хотите отображать в потоках/
Ну это я так для примера сделал.
Передача параметров в потоках происходит через TProcess = record
Код:
type
PProcess = ^TProcess;
TProcess = record
Thead1: Dword;
Thead2: Dword;
FA : Integer;
hEventTh1: THandle;
hEventTh2: THandle;
end;

var
ProcessRec: TProcess;


implementation

{$R *.dfm}

// работа потока 1
Function Thread1(Param: pointer): integer;
begin
try
//Запускаем цикл работы потока 1 он нужен для того чтобы поток не отключался
while true do
begin
if PProcess(Param)^.FA = 2 then
PProcess(Param).FA := 1;
SetEvent(PProcess(Param).hEventTh2); //включаем работу потока 2
  WaitForSingleObject(PProcess(Param).hEventTh1, INFINITE); //ждем когда 2 сделает нужные действия и включит 1
  ResetEvent(PProcess(Param).hEventTh1);
end;
finally
CloseHandle(PProcess(Param).hEventTh1);
endthread(0);
end;
end;

// работа потока 2
Function Thread2(Param: pointer): integer;
begin
try
//Запускаем цикл работы потока 2 он нужен для того чтобы поток не отключался
while true do
begin
if PProcess(Param)^.FA = 1 then
PProcess(Param).FA := 2;
SetEvent(PProcess(Param).hEventTh1); //включаем работу потока 1
  WaitForSingleObject(PProcess(Param).hEventTh2, INFINITE); //ждем когда 1 сделает нужные действия и включит 2
  ResetEvent(PProcess(Param).hEventTh2);
end;
finally
CloseHandle(PProcess(Param).hEventTh2);
endthread(0);
end;
end;

//запускаем потоки
procedure TForm1.Button1Click(Sender: TObject);
var
ThId: Dword;
begin
ProcessRec.hEventTh1:= CreateEvent(nil, true, False, nil); 
ProcessRec.hEventTh2:= CreateEvent(nil, true, False, nil);
ProcessRec.Thead1:= BeginThread(nil, 0, @Thread1, @ProcessRec, 0, ThId);
ProcessRec.Thead2:= BeginThread(nil, 0, @Thread2, @ProcessRec, 0, ThId);
end;

//Завершаем потоки
procedure TForm1.Button2Click(Sender: TObject);
begin
TerminateThread(ProcessRec.Thead1, 0);
TerminateThread(ProcessRec.Thead2, 0);
end;
В потоках нужно цикл задавать и прерывание иначе поток отключиться или процессор грузить будет, в вашем примере нужно ставить while not Terminated do begin если вы с классовым потоком работаете

Последний раз редактировалось Aliens_wolfs; 14.06.2015 в 20:27.
Aliens_wolfs вне форума Ответить с цитированием
Старый 14.06.2015, 20:06   #6
Antony41
Пользователь
 
Аватар для Antony41
 
Регистрация: 20.03.2009
Сообщений: 99
По умолчанию

Упфффф..... стойте стойте, дайте разобраться... И почему тут нет смайла с пистолетом у виска
Antony41 вне форума Ответить с цитированием
Старый 14.06.2015, 20:24   #7
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию

Цитата:
почему тут нет смайла с пистолетом у виска
Потому что самоубийство у нас разрешено только путем наезда на модератора )

А что именно ты там пишешь, если не секрет? Для чего тебе понадобились критические секции то?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 14.06.2015, 20:28   #8
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

Да да хотелось бы узнать для чего тебе такая работа потоков нужна
Aliens_wolfs вне форума Ответить с цитированием
Старый 14.06.2015, 20:33   #9
Antony41
Пользователь
 
Аватар для Antony41
 
Регистрация: 20.03.2009
Сообщений: 99
По умолчанию

Цитата:
А что именно ты там пишешь, если не секрет? Для чего тебе понадобились критические секции то?
Пишу модуль лицензий
один поток будет проверять параметры этой лицензии
второй поток вести учет времени работы программы
второй поток должен обновлять переменную которая содержится в первом потоке
а первый поток иногда поглядывать не изменилась ли та самая переменная хех)))

С потоками работаю впринципе давно, но вроде всё устраивало, а тут думаю дай еще раз почитаю, и на тебе влез в дебри многопоточности, теперь вылезти не получается, сижу читаю про TCriticalSections открыто уже 3 экземпляра DXE5.

Смотрите! Если третий поток должен изменять переменную которую содержит второй поток значит критическую секцию нужно создавать именно во втором или третьем потоке? или это не важно?
Можно ли её создать в главном потоке? а использовать во втором и в третьем при проверке и записи параметров
Можно ли использовать вместо Synchronize CS?

Последний раз редактировалось Stilet; 14.06.2015 в 22:30.
Antony41 вне форума Ответить с цитированием
Старый 16.06.2015, 02:57   #10
Turbine
Пользователь
 
Регистрация: 13.08.2008
Сообщений: 76
По умолчанию

А просто через указатель нельзя узнать? Вынести переменную за поток, до начала потока передать указатель и потом смотреть сколько душе угодно?
Turbine вне форума Ответить с цитированием
Ответ


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

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Проверить состояние потока своей функцией Shouldercannon Общие вопросы Delphi 6 01.10.2013 09:56
Узнать состояние TPopupMenu Alter Компоненты Delphi 2 07.03.2011 13:21
Как узнать номер потока из самого потока? GaMeSTeR Помощь студентам 0 03.12.2010 09:50
Узнать состояние кнопок мыши Cold_Night Общие вопросы Delphi 3 07.06.2009 21:36
Узнать состояние подключения Hottabych Работа с сетью в Delphi 8 03.03.2008 18:10