![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
WaitForSingleObject
ford © (2012-11-21 10:33:00)Добрый день!
Написал небольшую процедуру, для обработки регулярными выражениями (TRegExpr) большого массива данных, переданного пользователями. Из-за некорректных данных, процедура иногда повисает. Попытался исправлять ошибки в данных из-за которых происходит зависание, но всего предусмотреть не получается.
Решил вывести процедуру обработки в отдельный поток и завершать его принудительно если он работает более минуты. Наискавшись в интернет, сделал такой от класс:
type TThrSearch=class(TThread)
private
fData:String;
fExpr:String;
public
constructor create(expr,Data:String);
destructor destroy; override;
procedure Execute; override;
end;
Constructor TThrSearch.create;
begin
inherited Create(True);
fData:=data;
fExpr:=expr;
End;
destructor TThrSearch.destroy;
Begin
inherited;
End;
procedure TThrSearch.Execute;
Var r:TRegExpr;
k:Integer;
Begin
try
ReturnValue:=-1;
k:=0;
r:=TRegExpr.Create;
r.Expression:=fexpr;
if r.Exec(fData) Then
Begin
repeat
inc(k);
until not r.ExecNext;
End;
finally
r.Free;
ReturnValue:=k;
end;
End;
далее в программе создаю объект этого класса и выполняю метод Execute;
try
k:=0;
h:=TThrSearch.create(expr,st.Text);
h.Execute;
res:=WaitForSingleObject(h.Handle,2000);
if h.ReturnValue=-1 Then h.Terminate
Else k:=h.ReturnValue;
finally
h.Free;
result:=k;
end;
На сколько я понял
процедура WaitForSingleObject, должна останавливать основной поток программы и ждать сигнала от потока о завершении и если не дождалась то по таймауту передать управление основному потоку. Но
в при выполнении строки
res:=WaitForSingleObject(h.Handle,2000);
программа не зависимо от того завершился поток или нет, ждет указанный 2000 миллисекунд.
Подскажите, где ошибка, почему WaitForSingleObject, всегда ждет установленное таймаутом время и не реагирует на завершение процедуры execute?
sniknik (2012-11-21 18:08:00) [1]перепиши в стиле
// find next match:
// ExecNext;
// works same as
// if MatchLen [0] = 0 then ExecPos (MatchPos [0] + 1)
// else ExecPos (MatchPos [0] + MatchLen [0]);
// but it's more simpler !
// Raises exception if used without preceeding SUCCESSFUL call to
// Exec* (Exec, ExecPos, ExecNext). So You always must use something like
// if Exec (InputString) then repeat { proceed results} until not ExecNext;
для проблемного файла регулярки. проверь.
а лучше действительно -
DVM © (21.11.12 16:09) [38]
> Тогда может регулярное выражение выложишь на пару с проблемным файлом.
anatoly pogoretsky (2012-11-21 16:19:00) [2]> ford (21.11.2012 16:02:37) [37]
Ты уже не первый раз грубо
наезжаешь.
Медвежонок Пятачок (2012-11-21 16:19:00) [3]Но то что "зацикливание" происходит в недрах библиотеки RegExpr - факт.
Факт факт.
Конечно конечно.
Внутри внутри.
repeat
inc(k);
until not r.ExecNext;
DVM (2012-11-21 16:09:00) [4]
> программа работает, и на данный момент ПРАВИЛЬНО обработала
> несколько десятков тысяч текстов, сохранив в отдельную папочку,
> всего пару файликов с текстами которые вызвали "зависание".
> Исправить которые и подсунуть ей их еще раз не составит
> труда.
т.е на чистом проекте данные файлы вызывают проблемы у TregExpr? И проблема стабильно воспроизводится? Тогда может регулярное выражение выложишь на пару с проблемным файлом.
ford (2012-11-21 16:02:00) [5]
> Медвежонок Пятачок © (21.11.12 14:36) [36]
> чтобы тупо сосчитать все матчи внутри искомого твой цикл
> с inc() вообще не нужен.
Вы хотите чтобы я весь код привел в студию? :) Не говорите глупостей :)
при поиске места "зависания", я закоментил все что есть в цикле, и оттрасировал этот ExecNext. Нашел там этот "цикл" который состоял из нескольких вызовов. Но разбираться дальше с этой библиотекой - куча потраченного в пустую времени.
Но то что "зацикливание" происходит в недрах библиотеки RegExpr - факт. Может я не совсем корректно написал регулярное выражение, но опять же факт остается фактом, программа работает, и на данный момент ПРАВИЛЬНО обработала несколько десятков тысяч текстов, сохранив в отдельную папочку, всего пару файликов с текстами которые вызвали "зависание". Исправить которые и подсунуть ей их еще раз не составит труда.
Как говориться "Show must go on"
Медвежонок Пятачок (2012-11-21 14:36:00) [6]даже если он там есть,
то есть TRegExpr.Exec (AOffset: integer)
кроме того, чтобы тупо сосчитать все матчи внутри искомого твой цикл с inc() вообще не нужен.
все считается одним единственным вызовом
Медвежонок Пятачок (2012-11-21 14:31:00) [7]И чего?
Внутри ExecPrim есть цикл, который может быть бесконечным?
for i := 0 to NSUBEXP - 1 do begin
ford (2012-11-21 14:29:00) [8]
> Медвежонок Пятачок © (21.11.12 14:22) [33]
>
> Ты лучше поищи какую-либо цикличность внутри
Ну Вы блин даете. Сами фонарик-то не забудьте :)
....
Result := ExecPrim (Offset);
end; { of function TRegExpr.ExecNext
Медвежонок Пятачок (2012-11-21 14:22:00) [9]Ты лучше поищи какую-либо цикличность внутри
function TRegExpr.ExecNext : boolean;
var offset : integer;
begin
Result := false;
if not Assigned (startp[0]) or not Assigned (endp[0]) then begin
Error (reeExecNextWithoutExec);
EXIT;
end;
// Offset := MatchPos [0] + MatchLen [0];
// if MatchLen [0] = 0
Offset := endp [0] - fInputString + 1; //###0.929
if endp [0] = startp [0] //###0.929
then inc (Offset); // prevent infinite looping if empty string match r.e.
Result := ExecPrim (Offset);
end; { of function TRegExpr.ExecNext
фонарик только не забудь
ford (2012-11-21 14:19:00) [10]
> Медвежонок Пятачок © (21.11.12 14:17) [30]
>
> r.ExecNext уходит в бесконечный цикл.
>
> Кто тебе это сказал?
> Уверен, что это не твой repaet уходит в бесконечность?
Вы вообще видели Дельфи?
ford (2012-11-21 14:18:00) [11]
> Медвежонок Пятачок © (21.11.12 14:13) [29]
>
> что и требовалось доказать
Ну главное что ваше трольное себялюбие не затронуто.
Медвежонок Пятачок (2012-11-21 14:17:00) [12]r.ExecNext уходит в бесконечный цикл.
Кто тебе это сказал?
Уверен, что это не твой repaet уходит в бесконечность?
Медвежонок Пятачок (2012-11-21 14:13:00) [13]что и требовалось доказать
ford (2012-11-21 14:09:00) [14]
> sniknik © (21.11.12 13:32) [25]
>
> > стоит лезть в исходники TRegExpr или может проще и быстрее
> сделать как я?
> я вообще сомневаюсь, что ошибка в TRegExpr. она скорее у
> тебя, в "той" обработке...
обработка :
r:=TRegExpr.Create;
r.Expression:=fexpr;
if r.Exec(fData) Then
Begin
repeat
inc(k);
until not r.ExecNext;
End;
fExpr - строка с регулярным выражением
fdata - текст, размером от 1 до 100килобайт.
и fExpr и fData не пусты
для 17999 текстов все ОК, для одного, на тех же самых регулярных выражениях, r.ExecNext уходит в бесконечный цикл.
спрашивается
> ты ее возможно даже исправишь переписав по новому
Как вы себе это представляете? переписать библиотеку RegExpr? :)
Медвежонок Пятачок (2012-11-21 14:05:00) [15]Ставлю два байта на то, что бесконечный цикл написан не сорокиным (автором либы) а тобой.
И бесконечный он потому, что ты либо не умеешь писать регулярки, либо просто не умеешь анализировать что ты передаешь методам TRegExpr.
И вместо того, чтобы научиться программировать или хотя бы поставить в свой бесконечный цикл ограничение на макс. количество итераций или на время выполнения ты нагородил вторичный поток, вся польза от которого - возможность бросить поток, в котором начался твой бесконечный цикл. Причем именно бросить, а не остановить со всеми вытекающими и утекающими последствиями.
DVM (2012-11-21 13:36:00) [16]
> ford © (21.11.12 13:14) [22]
>
А что ты в тексте ищешь то? Уже неоднократно натыкался на случаи, когда без регулярок поиск ускорялся буквально в 100 раз.
sniknik (2012-11-21 13:32:00) [17]> стоит лезть в исходники TRegExpr или может проще и быстрее сделать как я?
я вообще сомневаюсь, что ошибка в TRegExpr. она скорее у тебя, в "той" обработке. и ты ее возможно даже исправишь переписав по новому, а возможно наплодишь еще глюков (уже в общем то, работает исключительно на взаимоисключениях)... как будет проще и быстрее еще вопрос.
ford (2012-11-21 13:20:00) [18]
> Медвежонок Пятачок © (21.11.12 12:51) [18]
>
> гениально.
> Был один поток, который искал.
> Стало два потока. Один ищет, другой вообще ничего не делает,
> а только ждет.
>
> Вопрос: зачем ему ждать, если он :
> 1. в это время сам может искать
> 2. в это время он нихрена вообще не делает, в том числе
> не обрабатывает сообщения и интерфейс gui не обновляется
>
> Ответ:
> А бес понятия, мне просто вторичные потоки нравятся.
Ответ:
См. пункт 0.
ford (2012-11-21 13:17:00) [19]
> это же у тебя подсчет количества вхождений фразы в текст?
не одной и не просто фразы, а целого множества "конструкций".
Для поиска фразы как последовательности символов я бы не заморачивался с регулярными выражениями.
ford (2012-11-21 13:14:00) [20]
> sniknik © (21.11.12 13:03) [19]
> это не у них, это у тебя, проблема. а "обходишь" у них.
Разбирать чужие исходники это всегда сложнее и дольше. Тем более, что "ошибка", например в тестовом примере возникает 1 на 18000, и как по Вашему, стоит лезть в исходники TRegExpr или может проще и быстрее сделать как я? А именно запустить в потоке и по срабатыванию таймаута отдать текст обратно юзеру, и продолжить обработку остальных 17999 "нормальных" текстов.
Мало того, но сделав именно так, я получил еще и кусок работающего кода, который можно использовать в других "зависающих" ситуациях.