Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2013.03.22;
Скачать: CL | DM;

Вниз

синхронизация потока.   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.062 c
15-1352901277
ЕщеОдинКакжеНадоели
2012-11-14 17:54
2013.03.22
Удалить кусок текста.


2-1333908120
Fr
2012-04-08 22:02
2013.03.22
Странное поведение Navigate в TwebBrowser


15-1328563233
Германн
2012-02-07 01:20
2013.03.22
Небольшой опрос по провайдерам и SMTP-серверам


2-1335502666
leklerk
2012-04-27 08:57
2013.03.22
Когда нужно использовать CoInitialize?


15-1353580932
NieL
2012-11-22 14:42
2013.03.22
Настройки программы