Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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: достойное решение! Завтра попробую опробировать на новом компе! Вот что называется простенько и со вкусом! Спасибо!


 
Leonid Troyanovsky ©   (2007-08-11 12:15) [41]


> Alex_C ©   (10.08.07 17:33) [38]

> Делфи заставить ЦП обновить тот или иной кэш БЕЗ правки
> кода TThread ?

Кэши процессоров обновятся при изменении общей переменной,
в нашем случае - FTerminated без всякого вмешательства.
Во всяком случае, для Intel.

--
Regards, LVT.



Страницы: 1 2 вся ветка

Форум: "Основная";
Текущий архив: 2007.10.28;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.58 MB
Время: 0.042 c
2-1191160170
Мурзик
2007-09-30 17:49
2007.10.28
Возможно ли?


6-1171023506
Alek_1
2007-02-09 15:18
2007.10.28
Как определить хендл открытого удаленного подключения к ине...


15-1191480540
MBo
2007-10-04 10:49
2007.10.28
50 лет первому ИСЗ


2-1191568762
em240
2007-10-05 11:19
2007.10.28
locate+настройка поиска


2-1191312738
webpauk
2007-10-02 12:12
2007.10.28
PopupMenu.Items.Width





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский