Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.10.28;
Скачать: CL | DM;

Вниз

Отловить ошибку в 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;
Скачать: CL | DM;

Наверх




Память: 0.59 MB
Время: 0.023 c
1-1186741765
Kolan
2007-08-10 14:29
2007.10.28
Одинаковые имена модулей в разных пакетах, как исправить


15-1190873947
F@T@L_Err0r
2007-09-27 10:19
2007.10.28
Ctrl+Alt+Del


15-1191495700
dRake
2007-10-04 15:01
2007.10.28
Настройка редактора кода в BDS 2006


15-1190980203
Booka Shade
2007-09-28 15:50
2007.10.28
Клик мышкой


2-1191401258
User_0
2007-10-03 12:47
2007.10.28
Как записать путь к БД в *.ini(Interbase)