![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Ошибка доступа при работе с потоками/нитями [D5, Win95/98, WinME, NT4, Win2k, WinXP]
Tkach_ © (2002-06-13 13:36:00)Столкнулся с проблемой при работе с потоками.
Поток А запускает поток В. Код выглядит следующим образом:
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>"
Помогите разобраться.
kull (2002-06-13 15:37:00) [1]
> Fiend © (13.06.02 15:27)
Ну за ник прошу прощения - очепятка вышла.
А насчет автора - так я-же не ради автора а ради дела...
Игорь Шевченко (2002-06-13 15:29:00) [2]Автору: Я воспроизвел код - ошибки нет. D5/NT4
Fiend (2002-06-13 15:27:00) [3]2kull
Ну для начала мой ник всё же FIENDа не FRIEND!!!
Ну а второе - моя проблема как раз правильно решена
А третье - автору то самому уже помоему уже ничего и не надо, он сам ничё не отвечает и не спрашивает
Внук (2002-06-13 15:22:00) [4]>>Игорь Шевченко © (13.06.02 15:19)
Надо дождаться, что автор ответит на Внук © (13.06.02 14:59), тогда видно будет :)
Игорь Шевченко (2002-06-13 15:19:00) [5]Внук © (13.06.02 15:15)
Похоже, я притормозил :-)
Внук (2002-06-13 15:15:00) [6]Народ, ну фактически здесь происходит в самом худшем случае
Syncronize(MainForm.Memo1.Lines.Add("что-то там")); - из потока А
Syncronize(MainForm.Memo1.Lines.Add("что-то там")); - из потока B
Оба вызова встраиваются в контекст главного потока, и все нормально живет. Иначе зачем нужен Syncronize???
kull (2002-06-13 15:14:00) [7]2Friend
Syncronize использует виндовскиую очередь сообщений для синхронизации так что одновременно вызваться метод Add из разных мест не может. Очевидно причина ваших глюков была в другом и похоже ваша проблемма решена не в правильном направлении.
Игорь Шевченко (2002-06-13 15:09:00) [8]Memo1 надо защищать критической секцией.
Рихтера учить наизусть, главу про синхронизацию потоков
Fiend (2002-06-13 15:05:00) [9]Я так думаю, что столь уважаемая АВ является причиной некорректного или несанкционированного системой совместного доступа к памяти, вполне возможно и из двух потоков
Внук (2002-06-13 15:03:00) [10]Но здесь и этого не будет, поскольку синхронизируются всего лишь UpdateLog - очень нехитрые процедуры
Внук (2002-06-13 15:01:00) [11]>>Fiend © (13.06.02 14:56)
Это может привести максимум к DeadLock, то есть обыкновенному повисанию приложения, но никак не к AV
Fiend (2002-06-13 14:59:00) [12]ааааахахахаххаа, и побольше доктор! ПОБОЛЬШЕ кода!!!!
Внук (2002-06-13 14:59:00) [13]BList тоже небезразмерный. Вообще этот код приведет к быстрому перерасходу памяти :) А то, что ошибка вылетает на той строке - так получилось :) Попробуйте ограничить выполнение каждого цикла хотя бы 10 итерациями и посмотрите, что получится.
Игорь Шевченко (2002-06-13 14:56:00) [14]Код UpdateLog в студию
Fiend (2002-06-13 14:56:00) [15]то что поток А например (вызвавший Synch) будет ждать завершения вызываемой процедуры.
Но второй то поток в это время не дремлет и тоже может вызвать Synchronyze(таже функция)
Поверьте, я вам дело говорю, у меня тоже были подобные проблемы с разделением ресурсов разными потоками одного приложения. Пока не начитался умных книжек про это дело и не стал юзать для разделения специальные классы, такие глюки были и я тоже не просекал в чём дело
Внук (2002-06-13 14:50:00) [16]>>Fiend © (13.06.02 14:44) "Synchronyze насколько я знаю синхронизит поток с главным потоком приложения" - вот именно, поэтому описываемая Вами ситуация здесь невозможна. Иначе, что Вы понимаете под словом "синхронизирует"?
Tkach_ (2002-06-13 14:48:00) [17]с мемо все в порядке. Ошибка выдается при первом вызове Synchronize(UpdateLog) в потоке В:
procedure TBThread.Execute;
begin
while not Terminated do
Synchronize(UpdateLog);// здесь ОШИБКА AV!!!
end;
Fiend (2002-06-13 14:44:00) [18]Я думаю что дело в возможности одновременного выполнения MainForm.Memo1.Lines.Add("что-то там");
разными потоками. Synchronyze насколько я знаю синхронизит поток с главным потоком приложения и то что вы в обоих потока А и Б делаете это не защизает Вас от одновременного выполнения метода АДД объекта Lines. А если один поток А вызвал этот метод но он не успел завершиться и тут вдруг проц переключился на выполнение другого потока Б, который тоже вдруг в этот момент вызвал тот же метод - сечете к чему это может привести???
Вам нужно использовать разделение ресурсов между потоками, это нада сделать при помощи Мьютексов или семафоров или т.д. что больше подходит
Ошибка может происходить в принципе не только из за метода АДД, мы ведь здесь весь код не видим
Внук (2002-06-13 14:38:00) [19]Переполнение Memo?
Tkach_ (2002-06-13 14:35:00) [20]код такой
procedure TАThread.UpdateLog;
begin
MainForm.Memo1.Lines.Add("что-то там");
StartBFlag:=(MainForm.Name1=Self.Name1);
end;
procedure TBThread.UpdateLog;
begin
MainForm.Memo1.Lines.Add("что-то там");
end;