Форум: "Основная";
Текущий архив: 2002.06.24;
Скачать: [xml.tar.bz2];
ВнизОшибка доступа при работе с потоками/нитями Найти похожие ветки
← →
Tkach_ (2002-06-13 13:36) [0]Столкнулся с проблемой при работе с потоками.
Поток А запускает поток В. Код выглядит следующим образом:
procedure TAThread.Execute;
begin
while not Terminated do
begin
Synchronize(UpdateLog);
if StartBFlag then
BList.Add(TBThread.Create(False));
end;
end;
procedure TBThread.Execute;
begin
while not Terminated do
Synchronize(UpdateLog);
end;
В результате генерируется ошибка: "access violation at <adress1>: write of adress <adress2>"
Помогите разобраться.
← →
Игорь Шевченко (2002-06-13 13:37) [1]Что делает UpdateLog ?
← →
Digitman (2002-06-13 13:44) [2]<adress1> , <adress2> - это для тебя диагностика, а не для Пушкина)
Значение <adress1> совместно с меню "Search|Find Error.." главного окна IDE Делфи, запустившего приложение врежиме встроенной отладки, укажет тебе модуль и строку в нем, при выполнении которой произошло AV
← →
Tkach_ (2002-06-13 14:10) [3]2 Игорь Шевченко ©
UpdateLog обоих потоков обновляет Мемо главной формы и устанавливает флаг StartBFlag (только поток А)
← →
Игорь Шевченко (2002-06-13 14:12) [4]Э...код бы...
← →
Tkach_ (2002-06-13 14:35) [5]код такой
procedure TАThread.UpdateLog;
begin
MainForm.Memo1.Lines.Add("что-то там");
StartBFlag:=(MainForm.Name1=Self.Name1);
end;
procedure TBThread.UpdateLog;
begin
MainForm.Memo1.Lines.Add("что-то там");
end;
← →
Внук (2002-06-13 14:38) [6]Переполнение Memo?
← →
Fiend (2002-06-13 14:44) [7]Я думаю что дело в возможности одновременного выполнения MainForm.Memo1.Lines.Add("что-то там");
разными потоками. Synchronyze насколько я знаю синхронизит поток с главным потоком приложения и то что вы в обоих потока А и Б делаете это не защизает Вас от одновременного выполнения метода АДД объекта Lines. А если один поток А вызвал этот метод но он не успел завершиться и тут вдруг проц переключился на выполнение другого потока Б, который тоже вдруг в этот момент вызвал тот же метод - сечете к чему это может привести???
Вам нужно использовать разделение ресурсов между потоками, это нада сделать при помощи Мьютексов или семафоров или т.д. что больше подходит
Ошибка может происходить в принципе не только из за метода АДД, мы ведь здесь весь код не видим
← →
Tkach_ (2002-06-13 14:48) [8]с мемо все в порядке. Ошибка выдается при первом вызове Synchronize(UpdateLog) в потоке В:
procedure TBThread.Execute;
begin
while not Terminated do
Synchronize(UpdateLog); // здесь ОШИБКА AV!!!
end;
← →
Внук (2002-06-13 14:50) [9]>>Fiend © (13.06.02 14:44) "Synchronyze насколько я знаю синхронизит поток с главным потоком приложения" - вот именно, поэтому описываемая Вами ситуация здесь невозможна. Иначе, что Вы понимаете под словом "синхронизирует"?
← →
Fiend (2002-06-13 14:56) [10]то что поток А например (вызвавший Synch) будет ждать завершения вызываемой процедуры.
Но второй то поток в это время не дремлет и тоже может вызвать Synchronyze(таже функция)
Поверьте, я вам дело говорю, у меня тоже были подобные проблемы с разделением ресурсов разными потоками одного приложения. Пока не начитался умных книжек про это дело и не стал юзать для разделения специальные классы, такие глюки были и я тоже не просекал в чём дело
← →
Игорь Шевченко (2002-06-13 14:56) [11]Код UpdateLog в студию
← →
Внук (2002-06-13 14:59) [12]BList тоже небезразмерный. Вообще этот код приведет к быстрому перерасходу памяти :) А то, что ошибка вылетает на той строке - так получилось :) Попробуйте ограничить выполнение каждого цикла хотя бы 10 итерациями и посмотрите, что получится.
← →
Fiend (2002-06-13 14:59) [13]ааааахахахаххаа, и побольше доктор! ПОБОЛЬШЕ кода!!!!
← →
Внук (2002-06-13 15:01) [14]>>Fiend © (13.06.02 14:56)
Это может привести максимум к DeadLock, то есть обыкновенному повисанию приложения, но никак не к AV
← →
Внук (2002-06-13 15:03) [15]Но здесь и этого не будет, поскольку синхронизируются всего лишь UpdateLog - очень нехитрые процедуры
← →
Fiend (2002-06-13 15:05) [16]Я так думаю, что столь уважаемая АВ является причиной некорректного или несанкционированного системой совместного доступа к памяти, вполне возможно и из двух потоков
← →
Игорь Шевченко (2002-06-13 15:09) [17]Memo1 надо защищать критической секцией.
Рихтера учить наизусть, главу про синхронизацию потоков
← →
kull (2002-06-13 15:14) [18]2Friend
Syncronize использует виндовскиую очередь сообщений для синхронизации так что одновременно вызваться метод Add из разных мест не может. Очевидно причина ваших глюков была в другом и похоже ваша проблемма решена не в правильном направлении.
← →
Внук (2002-06-13 15:15) [19]Народ, ну фактически здесь происходит в самом худшем случае
Syncronize(MainForm.Memo1.Lines.Add("что-то там")); - из потока А
Syncronize(MainForm.Memo1.Lines.Add("что-то там")); - из потока B
Оба вызова встраиваются в контекст главного потока, и все нормально живет. Иначе зачем нужен Syncronize???
← →
Игорь Шевченко (2002-06-13 15:19) [20]Внук © (13.06.02 15:15)
Похоже, я притормозил :-)
← →
Внук (2002-06-13 15:22) [21]>>Игорь Шевченко © (13.06.02 15:19)
Надо дождаться, что автор ответит на Внук © (13.06.02 14:59), тогда видно будет :)
← →
Fiend (2002-06-13 15:27) [22]2kull
Ну для начала мой ник всё же FIEND а не FRIEND!!!
Ну а второе - моя проблема как раз правильно решена
А третье - автору то самому уже помоему уже ничего и не надо, он сам ничё не отвечает и не спрашивает
← →
Игорь Шевченко (2002-06-13 15:29) [23]Автору: Я воспроизвел код - ошибки нет. D5/NT4
← →
kull (2002-06-13 15:37) [24]
> Fiend © (13.06.02 15:27)
Ну за ник прошу прощения - очепятка вышла.
А насчет автора - так я-же не ради автора а ради дела...
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2002.06.24;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.009 c