Форум: "Прочее";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];
ВнизСинхронизация и гонки потоков Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.45 MB
Время: 0.072 c