Форум: "Основная";
Текущий архив: 2007.10.28;
Скачать: [xml.tar.bz2];
ВнизОтловить ошибку в TThread Найти похожие ветки
← →
Alex_C © (2007-08-09 13:26) [0]Проблема: получаю данные из инета в отдельном потоке, чтоб не тормозить программу и отсылаю их в основную прогу. А вот если пользователь закрывает программу во время приема данных вылетает ошибка доступа - тут как бы все понятно - программы в памяти уже нет, а прием данных все продолжается и происходит обращение в никуда. Как этого избежать, кроме как не закрывать прогу до завершения приема данных? Пробовал в потоке ставить try... except - не помогает.
Прием данных осуществляю ф-цией InternetReadFile.
← →
tesseract © (2007-08-09 13:29) [1]при выходе из программы вызови TThread.WaitFor. Напиши нормальный обработчик terminate - т.е реализуй хотя бы базовый уровень контроля потоков.
← →
Loginov Dmitry © (2007-08-09 13:33) [2]Если крайне полезная функция:
TerminateProcess($FFFFFFFF, 0);
Панацея ото всех бед :))
← →
Сергей М. © (2007-08-09 13:34) [3]
> вылетает ошибка доступа
И все ?!
Прямо так вылетая и говорит, мол, ошибка доступа, а больше, мол, ничего не скажу ?
Вот уж не поверю)
А ведь это крайне важно для поиска "неисправности" !
← →
oxffff © (2007-08-09 13:54) [4]
> tesseract © (09.08.07 13:29) [1]
> при выходе из программы вызови TThread.WaitFor. Напиши нормальный
> обработчик terminate - т.е реализуй хотя бы базовый уровень
> контроля потоков.
В MSDN есть раздел Synchronization and Multiprocessor Issues.
Текущая реализация
procedure TThread.Terminate;
begin
FTerminated := True;
end;
Может не срабовать на многопроцессорной машине, если предположить, что эти потоки выполняются на разных процессорах.
Второй процессор может не обновить кэш. И попытаться отослать данные.
Так что реализацию Thread нужно поменять.
Для автора темы. Используй Event или Interlockedxxx для гарантии
← →
oxffff © (2007-08-09 13:55) [5]
> не срабовать
Не сработать
← →
Alex_C © (2007-08-09 19:13) [6]Спасибо за советы ребята! Буду пробовать!
← →
Alex_C © (2007-08-09 19:14) [7]Да для Сергей М.: ошибка такая: Ошибка доступа к user.dll - по моему так пишет. Могу ошибаться.
← →
Alex_C © (2007-08-09 19:25) [8]То oxffff: гм, только сейчас сообразил, что ошибка вылетает на новой многопроцессорной машине! На обычных пнях 4 ее нет! Выходит надо менять реализацию Terminate ? А как?
← →
oxffff © (2007-08-09 23:14) [9]Вот тебе пример для запуска +63 потока. При закрытии приложении ждет завершения всех 63 дополнительных потоков и выводит сообщение.
ThreadParams=packed record
Sync:Thandle;
end;
PThreadParams=^ThreadParams;
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
protected
params:ThreadParams;
public
{ Public declarations }
Threads:array[0..MAXIMUM_WAIT_OBJECTS-2] of THandle;
constructor Create(AOwner: TComponent);override;
destructor destroy;override;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure PendingCallInMainThread(Self:pointer);
begin
form1.Memo1.Lines.add("Ðàáîòàåò ïîòîê ");
end;
function ThreadProc(const params):DWORD;stdcall;
var Method:TMethod;
begin
Method.data:=nil;
Method.code:=@PendingCallInMainThread;
while WaitForSingleObject(ThreadParams(params).Sync,0)<>WAIT_OBJECT_0 do
begin
TThread.Synchronize(nil,TThreadMethod(Method));
sleep(1000);
end;
end;
{ TForm1 }
constructor TForm1.Create(AOwner: TComponent);
var i:integer;
tid:DWORD;
begin
inherited;
params.Sync:=CreateEvent(nil,TRUE,FALSE,nil);
if params.Sync<>INVALID_HANDLE_VALUE then
begin
for i:=low(Threads) to High(Threads) do Threads[i]:= CreateThread(nil,0,@ThreadProc,@params,0,tid);
end;
end;
destructor TForm1.destroy;
begin
inherited;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
SetEvent(params.Sync);
case WaitForMultipleObjects(Length(Threads),@Threads,TRUE, INFINITE) of
WAIT_OBJECT_0: Showmessage(Все дополнительные потоки завершены");
else //
end;
end;
← →
oxffff © (2007-08-09 23:36) [10]Из-за особенности работы функции,
If one of these handles is closed while the wait is still pending, the function"s behavior is undefined.
Модифицируй WaitForMultipleObjects на
WaitForMultipleObjects(Length(Threads),@Threads,TRUE, 5000)
← →
Leonid Troyanovsky © (2007-08-10 09:16) [11]
> oxffff © (09.08.07 23:14) [9]
> Вот тебе пример
Ночь в Крыму - все в дыму, и пушки стреляют.
--
Regards, LVT.
← →
oxffff © (2007-08-10 09:27) [12]
> Leonid Troyanovsky © (10.08.07 09:16) [11]
>
> > oxffff © (09.08.07 23:14) [9]
>
> > Вот тебе пример
>
> Ночь в Крыму - все в дыму, и пушки стреляют.
>
> --
> Regards, LVT.
Поясните, свою мысль
← →
Leonid Troyanovsky © (2007-08-10 10:47) [13]
> oxffff © (10.08.07 09:27) [12]
> Поясните, свою мысль
Мысль: пример неясный.
--
Regards, LVT.
← →
oxffff © (2007-08-10 10:54) [14]
> Мысль: пример неясный.
Вам? :)
← →
Leonid Troyanovsky © (2007-08-10 11:07) [15]
> oxffff © (10.08.07 10:54) [14]
> > Мысль: пример неясный.
> Вам? :)
По мне там, вообще, бред.
Из разряда сверхценных идей.
--
Regards, LVT.
← →
oxffff © (2007-08-10 11:11) [16]
> Leonid Troyanovsky © (10.08.07 11:07) [15]
>
> > oxffff © (10.08.07 10:54) [14]
>
> > > Мысль: пример неясный.
>
> > Вам? :)
>
> По мне там, вообще, бред.
> Из разряда сверхценных идей.
>
> --
> Regards, LVT.
Что конкретно вас не устраивает в коде?
← →
oxffff © (2007-08-10 11:14) [17]Сформулирую точнее.
Что конкретно вынуждает вас давать характеристику "бред"?
← →
Leonid Troyanovsky © (2007-08-10 12:02) [18]
> oxffff © (10.08.07 11:11) [16]
procedure PendingCallInMainThread(Self:pointer);
Method.code:=@PendingCallInMainThread;
На деструктор сил хватило, а метод формы влом?
За form1. - убивать из рогатки.
А Thread.Synchronize(nil,TThreadMethod(Method)) - растрогал до слез.
Да, ну невозможно такое всерьез обсуждать.
Псевдоглубокомысленная малограмотность.
> Модифицируй WaitForMultipleObjects на
> WaitForMultipleObjects(Length(Threads),@Threads,TRUE, 5000)
И ты полагаешь, что замена -1 на 5000
сделает ее поведение более определенным?
--
Regards, LVT.
← →
oxffff © (2007-08-10 12:35) [19]To Leonid Troyanovsky ©
Странно слышать от мастера.
Сейчас я вам повышу вашу квалификацию
А что вы не знаете как передаются параметры при register calling convention?
Напоминаю EAX, EDX, ECX и далее stack.
procedure PendingCallInMainThread(Self:pointer);
Можете даже так реализовать.
procedure PendingCallInMainThread;
Можете считать это анонимным методом.
>За form1. - убивать из рогатки.
За form1 в PendingCallInMainThread я так понимаю?
PendingCallInMainThread использовался как метод демострация того, что поток работает.
>А Thread.Synchronize(nil,TThreadMethod(Method)) - растрогал до слез.
Правильно и заплакали потому, что до SyncList по другому не добраться.
>И ты полагаешь, что замена -1 на 5000
>сделает ее поведение более определенным?
У вас будет более 3 секунд для гарантии того, что все потоки завершатся.
В данном конкретном примере проблем не будет. Что то опять незачет.
>Да, ну невозможно такое всерьез обсуждать.
>Псевдоглубокомысленная малограмотность.
Вы хоть поняли, что сами сказали?
В следующий раз давая кому-либо или чему-либо характеристику 100 раз подумайте. А потом промолчите. Быть может вы не правы.
>Да, ну невозможно такое всерьез обсуждать.
>Псевдоглубокомысленная малограмотность.
Сами хоть поняли, что сказали.
← →
MetalFan © (2007-08-10 12:45) [20]может стоит BeginThread вместо CreateThread использовать?!
да и приведенный пример слишком сложен для понимания человеку, который ранее не столь глубоко знаком с потоками...
← →
Leonid Troyanovsky © (2007-08-10 12:49) [21]
> oxffff © (10.08.07 12:35) [19]
> Можете считать это анонимным методом.
Не нужно никаких анонимных методов, а нужен обычный метод формы.
И не потребуется нелепых приседаний с TMethod и позорных form1.
> Правильно и заплакали потому, что до SyncList по другому
> не добраться.
Незнающим как синхронизироваться с главным потоком
надо пользовать TThread instead CreateThread
> У вас будет более 3 секунд для гарантии того, что все потоки
> завершатся.
Cначала у нас была вечность. Так что ж смутило?
Ремарка в msdn относится не к этому параметру.
> 100 раз подумайте. А потом промолчите. Быть может вы не
Может и не прав. А молчать невежливо, если спрашивают.
--
Regards, LVT.
← →
Leonid Troyanovsky © (2007-08-10 12:52) [22]
> MetalFan © (10.08.07 12:45) [20]
> может стоит BeginThread вместо CreateThread использовать?
Не можно, а нужно.
Стоит так поставить.
--
Regards, LVT.
← →
Сергей М. © (2007-08-10 12:58) [23]
> Leonid Troyanovsky © (10.08.07 12:49) [21]
oxffff(с) на протяжении последнего времени просто пыжит пуп в надежде нарисоваться глубочайшим в истории Мастаков исследователем геморроя, подаренного Борлангдом всем пользователям его шедевров)
Вот и все дела)
← →
oxffff © (2007-08-10 13:00) [24]
> Незнающим как синхронизироваться с главным потоком
> надо пользовать TThread instead CreateThread
Про хваленый Tthread читать [4]
> Cначала у нас была вечность. Так что ж смутило?
> Ремарка в msdn относится не к этому параметру.
Вы внимательно читаете MSDN?
lpHandles
[in] Pointer to an array of object handles.
......
If one of these handles is closed while the wait is still pending, the function"s behavior is undefined.
← →
oxffff © (2007-08-10 13:06) [25]
> Сергей М. © (10.08.07 12:58) [23]
>
> > Leonid Troyanovsky © (10.08.07 12:49) [21]
>
>
> oxffff(с) на протяжении последнего времени просто пыжит
> пуп в надежде нарисоваться глубочайшим в истории Мастаков
> исследователем геморроя, подаренного Борлангдом всем пользователям
> его шедевров)
>
> Вот и все дела)
Я в отличие от вас могу признать, что не могу знать все (да да я про DWORD alignment). Вы же свои ошибки не признаете, вместе с А.П.
Предпочитая отмолчаться.
Но не смотря на все это я не стал уважать меньше.
← →
Сергей М. © (2007-08-10 13:07) [26]
> oxffff
Чего ради ты пыжишься ?)
Рано или поздно модифицирующий это самое "FTerminated" процеccор сбросит и обновит кэш, и потоку, который выполняется там, остается только ждать (сколько потребуется), когда другой процессор, на котором выполняется интересующий поток, обновит свой кэш и обнаружит взведение этого флага.
В чем проблема ?
К чему все эти твои алгоритмические "изыски"-выкрутасы, если они в большинстве случаев нафих не нужны ?
← →
oxffff © (2007-08-10 13:07) [27]
> Но не смотря на все это я не стал уважать меньше.
Но не смотря на все это я не стал уважать вас меньше.
← →
Leonid Troyanovsky © (2007-08-10 13:12) [28]
> oxffff © (10.08.07 13:00) [24]
> > надо пользовать TThread instead CreateThread
> Про хваленый Tthread читать [4]
Но, это ж не воспрепятствовало использованию, например, Synchronize?
Чем, скажем, TThread.Handle хужее?
Да и речь там шла про FTerminated, ну и надо было вопрошаещему
рассказать как к нему применять InterlockedCompareExchange,
а не умничать ;)
> Вы внимательно читаете MSDN?
Стараюсь.
Только, связи между одним из хендлов и dwMilliseconds не заметил.
--
Regards, LVT.
← →
oxffff © (2007-08-10 13:13) [29]
> Чего ради ты пыжишься ?)
Я? С чего вы взяли?
По причине того, что FTerminated является Shared и execute по логике должен проверять ее. То и делать надо все c lock префиксом, либо с invalidate cash lines.
Посмотрите MSDN, хороший пример.
← →
oxffff © (2007-08-10 13:32) [30]
> Но, это ж не воспрепятствовало использованию, например,
> Synchronize?
Cвязь между ними есть, но она другая. Называется она deadLock. :)
← →
Leonid Troyanovsky © (2007-08-10 13:44) [31]
> oxffff © (10.08.07 13:32) [30]
> > Но, это ж не воспрепятствовало использованию, например,
> > Synchronize?
> Cвязь между ними есть, но она другая. Называется она deadLock.
Чем дальше, тем речь твоя становится менее разборчивой.
Связь между кем? Хендлы & dwMilliseconds?
Synchronize & Handle ?
И причем здесь deadlock.
--
Regards, LVT.
← →
Сергей М. © (2007-08-10 13:49) [32]
> Называется она deadLock. :)
А объяснить Автору, при каких условиях может возникнуть этот самый "дэдлок", - оно ниже твоего "достоинства" ?
Нужно обязательно пыжиться, демонстрируя логику "в особо извращенной форме" ?)
И кроме lock и invalidate cash lines разве не существуют способы прямо в коде Делфи заставить ЦП обновить тот или иной кэш БЕЗ правки кода TThread ?
Существуют)
На том и желаю тебе сосредоточиться, во благо и Автора и твоего "доброго имени")
← →
oxffff © (2007-08-10 14:02) [33]
> Чем дальше, тем речь твоя становится менее разборчивой.
Да все просто мой пример вызывает в deadlock. Поэтому и пришлось ставить 5000. Причина вызов Synchronize.
Я почему был уверен, что Synchronize ставит в очередь и продолжает работу.
Это моя вина
Ждем исправлений.
> Нужно обязательно пыжиться, демонстрируя логику "в особо
> извращенной форме" ?)
А вы что когда код пишите, тоже пыжитесь?
Я нет. Думаю и вы тоже.
>И кроме lock и invalidate cash lines разве не существуют способы прямо в >коде Делфи заставить ЦП обновить тот или иной кэш БЕЗ правки кода >TThread ?
Да много чего существует.
← →
Сергей М. © (2007-08-10 14:09) [34]
> когда код пишите, тоже пыжитесь?
Код, в котором я хотя бы в какой-то мере не уверен, - да, "пыжусь" и пишу, пишу и "пыжусь" ...)
Но НЕ для выноса в кач-ве публичного жупела) ... Жупела по поводу и без повода) ..
> много чего существует
Вот и нарисуй одно из них)
ЗАЧЕМ провоцировать весьма непосвещенного Автора хотя бы на "CreateThread", если он грозит ему еще и бОльшими неприятностями с учетом его знаний ?
Репу-то почеши)..
← →
oxffff © (2007-08-10 15:46) [35]Вот исправленный код.
ThreadParams=packed record
Sync:Thandle;
ThreadCount:DWORD;
end;
PThreadParams=^ThreadParams;
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
params:ThreadParams;
public
{ Public declarations }
Threads:array[0..MAXIMUM_WAIT_OBJECTS-2] of THandle;
constructor Create(AOwner: TComponent);override;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure PendingCallInMainThread(Self:pointer);
begin
form1.Memo1.Lines.add("Thread works ");
end;
function ThreadProc(const params):DWORD;stdcall;
var Method:TMethod;
begin
Method.data:=nil;
Method.code:=@PendingCallInMainThread;
while WaitForSingleObject(ThreadParams(params).Sync,0)<>WAIT_OBJECT_0 do
begin
TThread.Synchronize(nil,TThreadMethod(Method));
sleep(1000);
end;
InterlockedIncrement(integer((@ThreadParams(params).ThreadCount)^));
end;
constructor TForm1.Create(AOwner: TComponent);
var i:integer;
tid:DWORD;
begin
inherited;
params.Sync:=CreateEvent(nil,TRUE,FALSE,nil);
if params.Sync<>INVALID_HANDLE_VALUE then
begin
for i:=low(Threads) to High(Threads) do Threads[i]:= CreateThread(nil,0,@ThreadProc,@params,0,tid);
end;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
SetEvent(params.Sync);
while params.ThreadCount<length(Threads) do CheckSynchronize;
Showmessage("Threads None");
end;
← →
oxffff © (2007-08-10 15:54) [36]Небольшая оптимизация
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
SetEvent(params.Sync);
while params.ThreadCount<length(Threads) do
begin
CheckSynchronize;
sleep(300);
end;
....
Showmessage...
end;
← →
Lacmus © (2007-08-10 16:28) [37]>Alex_C © (09.08.07 19:25) [8]
SetProcessAffinityMask
← →
Alex_C © (2007-08-10 17:33) [38]Ну блин не ожидал такой полемики по поводу моего вопроса :)
К сожалению до конца не все ясно.
Конкретные попросы по вышепрочитанному:
То Сергей М.: не укажешь ли конкретно способы прямо в коде Делфи заставить ЦП обновить тот или иной кэш БЕЗ правки кода TThread ?
То Lacmus: SetProcessAffinityMask - это заставить процесс выполняться на конкретном процесоре. Т.е. ты предлагаешь изначально все треды запускать на одном проце, я так понимаю?
← →
Lacmus © (2007-08-10 18:02) [39]>Alex_C © (10.08.07 17:33) [38]
Да, треды будут запускаться на одном процессоре (думаю это будет адекватное решение)
← →
Alex_C © (2007-08-10 22:59) [40]То Lacmus: достойное решение! Завтра попробую опробировать на новом компе! Вот что называется простенько и со вкусом! Спасибо!
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2007.10.28;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.048 c