Форум: "Начинающим";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];
Внизсинхронизация потока. Найти похожие ветки
← →
vegarulez (2012-09-18 21:34) [0]Доброго времени суток мастерам! обычно делал работу с ком портами, отправку данных в интернет и прочие процедуры которые замораживают приложение в отдельных потоках для псевдопарралельной работы прилоджения. Делал как и описано в примерах через TThread определяя его обычно в отдельном Unit чтобы не засорять приложение - и проводил потом синхронизацию полученных потоком данных с основным приложением с помощью Synchronize, либо используя property определённое в основновном потоке. Потребовалось сделать работу приложения с именованными каалами. скачал примеры начал разбираться, (писал уже как то тему про это - большое спасибо Сергей М. - помог разобраться) - вроде на основе примеров сделал всё что надо, но не пойму, как мне синхронизовать работу потока, который читает с именованного канала данные с основным потоком. В том примере, с которого копипастил и разбирался - сделано не так как я обычно делаю через TThread в отдельном юните - а сделано в основном коде создание потока и работа с ним. И когда в код пытаюсь вставить метод Synchronize для того чтобы добавить результаты работы потока - считанные из канала данные в TMemo или другие контролы и\или переменные основного потока - компилятор ругается. Прошу подсказать как правильно сделать работу с потоком который создаётся с помощью
// Создать поток чтения из канала.
if BeginThread (nil, 0, @ReadPipe, @hPipe, 0, Dummy)=0 then
;
и описан в основном же потоке какprocedure ReadPipe (hPipe: PHANDLE);
var
inBuf: array[0..IN_BUF_SIZE] of AnsiChar;
bytesRead: DWORD;
rc: Boolean;
lastError: DWORD;
hEventRd: THANDLE;
OverLapRd: OVERLAPPED;
bytesTrans: DWORD;
s,s_err:ansistring;
i:integer;
begin
...
// тут работает поток на чтение из канала
//записываю в property результат работы потока
Formmain.Ftc_xml_ans:=s;
//Formmain.Memo2.Lines.Add(s); // тут раньше писал напрямую в контрол - что ни есть гуд
// ввёл процедуру которая делает по сути тоже что написано строчкой выше помещая из property в мемо - т.е. ни есть гуд - по идее вот тут бы надо сделать Synchronize (Formmain.tcadr_memo)
Formmain.tcadr_memo;
s:="";
// Если соединение с каналом разорвано, завершить программу
PostMessageW (hWndClient, WM_GO_AWAY, 0,0);
ExitThread(0);
end;
Когда ReadPipe отрабатывает в локальных переменных у меня содержатся результаты чтения из именованного канала - сообственно вопрос в том - как их корректно записать в контролы - т.е. выполнить правильныую синхронизацию с основным потоком.
Завёл в основном потоке property под эти данные - запихиваю их туда? в конце работы а не напрямую в контролы. Сделал процедуру - которая запускается перед убийством потока ReadPipe и которая помещает значение property в контролы - но это тоже не правильно... по идее в обычно Tthread как раз эта процедура должна делаться через Synchronize("Эта процедура")... но тут ещё раз повторюсь - вставляю Synchronize - компилтор ругается...
Вообщем нид хелп! подскажите пожалуйста как правильно сделать... а то ошибки приложения валятся из за этого постоянно (
← →
vegarulez (2012-09-18 21:38) [1]* очепятался
Завёл в основном потоке property под эти данные - запихиваю их туда, в конце работы, а не напрямую в контролы.
← →
Сергей М. © (2012-09-18 22:52) [2]
> вставляю Synchronize - компилтор ругается
Наверно матерно, раз ты не привел конкретный фрагмент того что и куда ты "вставляешь" и как он при этом "ругается" ..
← →
Сергей М. © (2012-09-18 22:56) [3]
> //Formmain.Memo2.Lines.Add(s); // тут раньше писал напрямую
> в контрол - что ни есть гуд
Вот с Mемо-то как раз таки и гуд - метод Add() приводит к SendMessage(), что есть один из гуд-способов синхронизации.
← →
Сергей М. © (2012-09-18 23:00) [4]
> писал напрямую
Тo бишь вызов Memo.Lines.Add на самом деле не является методом, "писующим напрямую" - он посылает сообщение окну стандартного виндового мемо-контрола, основной (или неважно какой) поток в нужное ему время выгребает это сообщение и отрабатывает его вполне себе синхронно.
← →
vegarulez (2012-09-19 21:09) [5]Так а если
Formmain.Memo2.Lines.Add(s);
используется внутри дочернего потока? получается он будет ждать пока основной поток сделает add в мемо и только потом перейдёт к исполнению следующей строки своего кода(кода доп. потока)?
← →
vegarulez (2012-09-19 21:47) [6]И ещё вопрос...
я запускаю процедуру
Formmain.tcadr_memo;
в которой используются переменные основного потока для работы с xml, описаные в основном потоке, я в них передаю данные помещённые в property, которые получил в потоке. Далее в процедуре работаю с ними(парсю сравниваю делаю запросы в БД и т.п. вообщем работаю полностью с переменными и контролами основного потока ) и потом уже помещаю результаты этой работы в мемо основной формы. А процедуру эту вызываю из под доп.потока, передавая в неё результат через property.
поэтому вот и хочу спросить получается что это же не совсем правильно - т.е. поток вывзывает процедуру - та работает с переменными из главного потока - а в это время доп.поток висит + передача переменых без синхронизации и вызов из под потока и работа с переменными описанными в основном потоке - короче, я так думаю, что получается вкусная и питательная каша... Или я не прав? просто при использовании отдельного юнита и tthread я делал synchronize такой процедуры и вроде всё работало без сбоев.
← →
Сергей М. © (2012-09-20 16:25) [7]
> vegarulez (19.09.12 21:09) [5]
Да, будет ждать.
> поток вывзывает процедуру - та работает с переменными из
> главного потока - а в это время доп.поток висит
А в это время основной поток, ничего не зная о том что делает в этот момент дополнительный поток, лезет в свои же переменные и работает с ними - читает, модифицирует .. И вместо вожделенной каши получается отвратительная некалорийная опасная для здоровья программы алгоритмическая похлебка)
← →
vegarulez (2012-09-20 18:49) [8]вот-вот и я о том же и говорю... зачётная бурда получается... поэтому вопрос как... как правильно синхронизировать. почитал некоторые статьи - нашёл описание с использованием критических секций - сделал через критические секции - потестирую - посомтрю как будет себя вести. я открываю критическую секцию перед вызовом процедуры которая работает с переменными основного потока - передаю в неё результаты работы доп потока записав его в доп потоке в property и в процедуре обращаюсь к property и закрываю критическую секцию после окончания обращания к процедуре в блоке finally разумеется... через try чтобы если процедура упадёт критическая секция была закрыта. ...
5 минут полёт нормальный... пока тестирую.
← →
Сергей М. © (2012-09-20 22:07) [9]Упарил ты своими property)
Я до сих пор не пойму кто у тебя там к кому и к каким-то там property обращается ..
Проиллюстрируй во фрагментах кода ..
← →
vegarulez (2012-09-21 18:55) [10]
Unit Main;
uses
...
property tc_xml_cmd:ansistring read Ftc_xml_cmd write Ftc_xml_cmd;
...
implementation
...
ну и в процедуре сделал работу через критические секцииtry
CritSec.Enter; // открываем секцию
Formmain.Ftc_xml_ans:=s; // помещаем в проперти данные полученные в потоке из канала
Formmain.tcadr_memo; // процедура работы с данными из канала записанными в property
finally
CritSec.Leave; // закрываем
end
← →
Сергей М. © (2012-09-23 19:05) [11]А основной поток у тебя, надо понимать, обращается к свойству tc_xml_cmd когда ему вздумается, ничего не зная про критическую секцию ?
Если же знает, то почему не поместить работу с крит.секцией прямо в геттер и сеттер свойства tc_xml_cmd ?
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.073 c