![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Отловить ошибку в TThread [D7, WinXP]
Alex_C © (2007-08-09 13:26:00)Проблема: получаю данные из инета в отдельном потоке, чтоб не тормозить программу и отсылаю их в основную прогу. А вот если пользователь закрывает программу во время приема данных вылетает ошибка доступа - тут как бы все понятно - программы в памяти уже нет, а прием данных все продолжается и происходит обращение в никуда. Как этого избежать, кроме как не закрывать прогу до завершения приема данных? Пробовал в потоке ставить try... except - не помогает.
Прием данных осуществляю ф-цией InternetReadFile.
Leonid Troyanovsky (2007-08-10 12:49:00) [21]
> oxffff © (10.08.07 12:35) [19]
> Можете считать это анонимным методом.
Не нужно никаких анонимных методов, а нужен обычный метод формы.
И не потребуется нелепых приседаний с TMethod и позорных form1.
> Правильно и заплакали потому, что до SyncList по другому
> не добраться.
Незнающим как синхронизироваться с главным потоком
надо пользовать TThread instead CreateThread
> У вас будет более 3 секунд для гарантии того, что все потоки
> завершатся.
Cначала у нас была вечность. Так что ж смутило?
Ремарка в msdn относится не к этому параметру.
> 100 раз подумайте. А потом промолчите. Быть может вы не
Может и не прав. А молчать невежливо, если спрашивают.
--
Regards, LVT.
MetalFan (2007-08-10 12:45:00) [22]может стоит BeginThread вместо CreateThread использовать?!
да и приведенный пример слишком сложен для понимания человеку, который ранее не столь глубоко знаком с потоками...
oxffff (2007-08-10 12:35:00) [23]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 раз подумайте. А потом промолчите. Быть может вы не правы.
>Да, ну невозможно такое всерьез обсуждать.
>Псевдоглубокомысленная малограмотность.
Сами хоть поняли, что сказали.
Leonid Troyanovsky (2007-08-10 12:02:00) [24]
> 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 11:14:00) [25]Сформулирую точнее.
Что конкретно вынуждает вас давать характеристику "бред"?
oxffff (2007-08-10 11:11:00) [26]
> Leonid Troyanovsky © (10.08.07 11:07) [15]
>
> > oxffff © (10.08.07 10:54) [14]
>
> > > Мысль: пример неясный.
>
> > Вам? :)
>
> По мне там, вообще, бред.
> Из разряда сверхценных идей.
>
> --
> Regards, LVT.
Что конкретно вас не устраивает в коде?
Leonid Troyanovsky (2007-08-10 11:07:00) [27]
> oxffff © (10.08.07 10:54) [14]
> > Мысль: пример неясный.
> Вам? :)
По мне там, вообще, бред.
Из разряда сверхценных идей.
--
Regards, LVT.
oxffff (2007-08-10 10:54:00) [28]
> Мысль: пример неясный.
Вам? :)
Leonid Troyanovsky (2007-08-10 10:47:00) [29]
> oxffff © (10.08.07 09:27) [12]
> Поясните, свою мысль
Мысль: пример неясный.
--
Regards, LVT.
oxffff (2007-08-10 09:27:00) [30]
> Leonid Troyanovsky © (10.08.07 09:16) [11]
>
> > oxffff © (09.08.07 23:14) [9]
>
> > Вот тебе пример
>
> Ночь в Крыму - все в дыму, и пушки стреляют.
>
> --
> Regards, LVT.
Поясните, свою мысль
Leonid Troyanovsky (2007-08-10 09:16:00) [31]
> oxffff © (09.08.07 23:14) [9]
> Вот тебе пример
Ночь в Крыму - все в дыму, и пушки стреляют.
--
Regards, LVT.
oxffff (2007-08-09 23:36:00) [32]Из-за особенности работы функции,
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)
oxffff (2007-08-09 23:14:00) [33]Вот тебе пример для запуска +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.SyncINVALID_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;
Alex_C (2007-08-09 19:25:00) [34]То oxffff: гм, только сейчас сообразил, что ошибка вылетает на новой многопроцессорной машине! На обычных пнях 4 ее нет! Выходит надо менять реализацию Terminate ? А как?
Alex_C (2007-08-09 19:14:00) [35]Да для Сергей М.: ошибка такая: Ошибка доступа к user.dll - по моему так пишет. Могу ошибаться.
Alex_C (2007-08-09 19:13:00) [36]Спасибо за советы ребята! Буду пробовать!
oxffff (2007-08-09 13:55:00) [37]
> не срабовать
Не сработать
oxffff (2007-08-09 13:54:00) [38]
> 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 для гарантии
Сергей М. (2007-08-09 13:34:00) [39]
> вылетает ошибка доступа
И все ?!
Прямо так вылетая и говорит, мол, ошибка доступа, а больше, мол, ничего не скажу ?
Вот уж не поверю)
А ведь это крайне важно для поиска "неисправности" !
Loginov Dmitry (2007-08-09 13:33:00) [40]Если крайне полезная функция:
TerminateProcess($FFFFFFFF, 0);
Панацея ото всех бед :))