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

Вниз

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

 
megavoid (other pc)   (2012-07-29 11:02) [0]

Доброго выходного дня, уважаемые мастера! Я в очередной раз перемудрил сам себя.

Имеется приложение-многозвенка, ехе запускается у клиента и гоняет трафик между удалённым сервером и внешней сторонней железкой. Сетевая часть с самого начала была задумана в потоке. Пока чтение данных с железки было функцией в главном потоке, всё было хорошо. Проблемы начались при выносе цикла чтения в отдельный поток.

Архитектура потока такова:
procedure ReaderThread.Execute;
begin
while not Termiated do begin
 res := ReadDataFromHardware;
 if not (res) continue
 else begin
 Synchronize(procedure begin  // race!!!
   SyncRecord.Fields := SetThemFromHardwareData;
 end);
 SetEvent(E1);
 end;
end;
end;


главный поток:
procedure HardwareSession;
begin
Reader := ReaderThread.Create(True, DataForThread);
Reader.Resume;
SendDataToHardware(BeginDataExchange);
repeat
res := WaitForMultipleObjects(Objects,1);
case
WAIT_SIGNALED_E1: Actions;
WAIT_SIGNALED_OTHERS: SendDifferentDataToHardware or SetStopFlag;
dec(timeout);
// тут было ReadDataFromHardware (без потока)
until StopFlag or Timeout=0;
end;


Судя по отладочной печати: ReaderThread запускается, получает данные, но его Synchronize выполняется только после того, как repeat завершается по таймауту, когда уже поздно.

Если же в главном потоке перед последней строчкой until StopFlag or Timeout вкорячить ProcessMessages, то получаю главенство уже читающего потока (readfromhardware довольно шустрая), в лог записывается, что поток читалки не отдаёт управление главному, пока не получит всю очередь данных от железки (пока ей даёт ProcessMessages?), и уже только после этого repeat входит на следующую итерацию,  видит событие Е1 (а его уже на самом деле 100 раз подняли), хочет выполнить Action, но теперь тоже уже поздно, железка не дождалась ответа и ушла по таймауту, о чём поток читалки грустно и сообщает уже другим событием на следующей итерации ProcessMessages.

Выше я упоминал про сетевой поток. Его синхронизация организована точно так же, как и в ReaderThread - Synchronize(proc begin SyncRecord.SetFields end); затем установка соответствующего Eventа. Получает он данные так же - waitformultiple(Events), по событию через Synchronize забирает данные и занимается далее своей сетевой работой. Всё синхронизировалось нормально (отладочные сообщения выводятся в нужной последовательности).

Парадокс - с сетевым потоком нормально, а с ещё одним ненормально??? Подозреваю, что это называется, скорее, не парадокс, а криворукость. Перечитал статью GunSmokera, перечитал Рихтера, справку, понимаю, что попал на классические гонки, но всё равно туплю. Уважаемые мастера, подскажите, пожалуйста, куда копать?


 
Cobalt ©   (2012-07-29 13:13) [1]

Для начала определись, как ты хочешь чтобы потоки работали, а потом реализуй это.
И, раз уж ты пользуешься методом Synchronize, узнай как он работает.


 
megavoid ©   (2012-07-30 09:22) [2]

Cobalt, покопался, Synchronize создаёт событие, входит в критическую секцию, выполняет переданную подпрограмму, выходит из секции.
Я и говорю, перемудрил я сам себя с архитектурой (( печально переписываю



Страницы: 1 вся ветка

Текущий архив: 2013.03.22;
Скачать: CL | DM;

Наверх




Память: 0.47 MB
Время: 0.085 c
6-1260272923
krisri
2009-12-08 14:48
2013.03.22
Сокеты


2-1334410535
tolbase
2012-04-14 17:35
2013.03.22
Delphi 7! Как отловить событие minimize формы?


15-1351699705
ПростоФАН
2012-10-31 20:08
2013.03.22
Помощь в разработке по


3-1280406421
Alekcey
2010-07-29 16:27
2013.03.22
raised exception ... in module IDODBC32.DLL


15-1342466570
MsGuns
2012-07-16 23:22
2013.03.22
Умер Джон Лорд