Форум: "Основная";
Текущий архив: 2003.12.16;
Скачать: [xml.tar.bz2];
ВнизTThread... Найти похожие ветки
← →
DeScriptor (2003-12-05 08:02) [0]Люди, помогите, плз!!!
У меня тут полные и абсолютные вилы!
В общем, ситуация такова:
Есть прога, работающая в основном с текстом, я начал реализовывать в ней поиск текста и стало плохо. Система такая:
1. Из главного меню главного окна Главного окна выбирается пункт Find Text, и в обработчике OnClick вызывается метод FindWin.ShowModal.
2. В появившемся окне мы пишем искомый текст и нажимаем кнопку Find, в обработчике OnClick идет следующий текст:
procedure TFindWin.FindBtnClick(Sender: TObject);
begin
FindWin.Visible:=false;
SearchThread:=TSearchEngine.Create(false);
FindWin.Close;
end;
При этом на строке SearchThread:=TSearchEngine.Create(false);<.code> стоит breakpoint! Далее происходят разные вещи: либо исполнение проги останавливается на брикпоинте, либо система жутко виснет, так что даже TaskManager не хочет вылезать, и приходится нажимать Reset; либо система жутко тормозит, но прога убивается-таки сочетанием Ctrl+F2 из Дельфей. В последнем случае умирает начисто переключение раскладки клавы: в любой проге можно переключиться в русский, потом обратно в английский и на этом переключения заканчиваются (Language Bar is expired (?) =)) до следующий перезагрузки. По какому принципу происходит то или иное событие я не понял - слово я ищу одно и то же, текст гружу один и тот же...
На всякий пожарный привожу код thread"а, который у меня занимается поиском текста (прошу не судить строго за корявость):
procedure TSearchEngine.Execute;
var MatchCount,i,j,k,Count:word;
SearchString,TempStr:string;
Found:boolean;
MatchIndexes:array of word;
begin
SearchString:=FindWin.SearchString.Text;
MatchCount:=0;
for i:=0 to High(StringArray) do begin
TempStr:=StringArray[i].Text;
if not FindWin.MatchCase.Checked then begin
TempStr:=AnsiUpperCase(TempStr);
SearchString:=AnsiUpperCase(SearchString);
end;
if SearchString>TempStr then Continue;
for j:=1 to Length(TempStr) do begin
Found:=false;
if SearchString[1]=TempStr[j] then begin
Count:=0;
for k:=j to Length(TempStr) do begin
Count:=Count+1;
if SearchString[Count]=TempStr[k] then Found:=True else break;
if Count=Length(SearchString) then begin
MatchCount:=MatchCount+1;
SetLength(MatchIndexes,MatchCount);
MatchIndexes[MatchCount]:=StringArray[i].Index;
Break;
end else Found:=false;
end;
if Found then break;
end;
if Found then break;
end;
end;
if MatchIndexes=nil then MessageBox(0,"Nothing was found! :-(","Results",MB_ICONERROR)
else begin
for i:=0 to Length(MatchIndexes)-1 do ResultBrowser.ResultList.Items.Add(IntToStr(MatchIndexes[i]));
ResultBrowser.Show;
MatchIndexes:=nil
end;
end;
Сразу оговорюсь, что для большей удобочитаемости я заменил некоторые названия переменных (а то в экран не влезали =)), так что если найдктся опечатки - проблема, скорее всего, не в них. По крайней мере, компилятор ни на что не ругается, и прога стартует. С переменным успехом. =)
← →
MBo (2003-12-05 08:07) [1]1. Ты закрываешь форму, к которой обращаешься
2. И вообще обращаешься к ней без синхронизации
← →
Digitman (2003-12-05 08:20) [2]
procedure TFindWin.FindBtnClick(Sender: TObject);
begin
SearchThread:=TSearchEngine.Create(True);
SearchThread.SearchString := SearchString.Text;
SearchThread.MatchCase := MatchCase.Checked;
SearchThread.FreeOnTerminate := True;
SearchThread.OnTerminate := DoOnTerminate;
SearchThread.Resume;
ModalResult := mrOk;
end;
procedure TSearchEngine.Execute;
var MatchCount,i,j,k,Count:word;
SearchString,TempStr:string;
Found:boolean;
MatchIndexes:array of word;
begin
MatchCount:=0;
for i:=0 to High(StringArray) do begin
TempStr:=StringArray[i].Text;
if not MatchCase then begin
TempStr:=AnsiUpperCase(TempStr);
SearchString:=AnsiUpperCase(SearchString);
end;
if SearchString>TempStr then Continue;
for j:=1 to Length(TempStr) do begin
Found:=false;
if SearchString[1]=TempStr[j] then begin
Count:=0;
for k:=j to Length(TempStr) do begin
Count:=Count+1;
if SearchString[Count]=TempStr[k] then Found:=True else break;
if Count=Length(SearchString) then begin
MatchCount:=MatchCount+1;
SetLength(MatchIndexes,MatchCount);
MatchIndexes[MatchCount]:=StringArray[i].Index;
Break;
end else Found:=false;
end;
if Found then break;
end;
if Found then break;
end;
end;
end;
procedure TFindWin.DoOnTerminate;
begin
with SearchThread do
if MatchIndexes=nil then
MessageBox(0,"Nothing was found! :-(","Results",MB_ICONERROR)
else
begin
for i:=0 to Length(MatchIndexes)-1 do ResultBrowser.ResultList.Items.Add(IntToStr(MatchIndexes[i]));
ResultBrowser.Show;
MatchIndexes:=nil;
end;
end;
← →
DeScriptor (2003-12-05 08:22) [3]2MBo
Где я закрываю форму я понял, но это значения не имеет: подобная конструкция у меня уже эффективно работает: форма вызывает процесс, который вообще и не собирается обновлять что-либо, кроме своих переменных и ListBox"а на форме, которая вообще первый раз становится видна после успешных поисков.
Что же касается обращения без синхронизации, то нельзя ли с этого момента поподробнее? Я так понял, что синхронизация есть вещь полезная только в том случае, если у нас в процессе цикл, за каждую итерацию которого нужно что-нибудь обновить за пределами модуля с процессом. Или я не прав?
← →
Digitman (2003-12-05 08:26) [4]да, вот еще что
переменнык SearchString, Count, MatchIndexes убери из списка локальных и сделай их public-свойствами класса TSearchEngine. Туда же добавь св-во MatchCase: Boolean;
строчку
MatchIndexes:=nil;
вообще убери
← →
ЮЮ (2003-12-05 08:31) [5]> исполнение проги останавливается на брикпоинте, либо система жутко виснет, так ...
а что в конструкторе TSearchEngine.Create ? Поставь breakpoint в нём, а не снаружи.
← →
DeScriptor (2003-12-05 08:38) [6]2Digitman
Во-первых, огромное спасибо за столь подробный ответ! Действительно, очень приятно, а во-вторых... Не могли бы Вы обосновать, почему Вы написали так, а не иначе? Просто я себя считаю еще абсолютным новичком в области Дельфи и программирования в целом и много еще не знаю или просто не понимаю, соответственно, мне ужасно интересно ПОЧЕМУ из двух (или более) возможных вариантов кода стоит выбрать именно один конкретный?
Кстати, забыл сказать, TSearchEngine находится у меня в отдельном юните, как сделал Дельфи. А FindWin - в другом юните.
← →
DeScriptor (2003-12-05 08:39) [7]2ЮЮ
Обычный конструктор процесса:
constructor TThread.Create(CreateSuspended: Boolean);
{$IFDEF LINUX}
var
ErrCode: Integer;
{$ENDIF}
begin
inherited Create;
AddThread;
FSuspended := CreateSuspended;
FCreateSuspended := CreateSuspended;
{$IFDEF MSWINDOWS}
FHandle := BeginThread(nil, 0, @ThreadProc, Pointer(Self), CREATE_SUSPENDED, FThreadID);
if FHandle = 0 then
raise EThread.CreateResFmt(@SThreadCreateError, [SysErrorMessage(GetLastError)]);
{$ENDIF}
{$IFDEF LINUX}
sem_init(FCreateSuspendedSem, False, 0);
ErrCode := BeginThread(nil, @ThreadProc, Pointer(Self), FThreadID);
if ErrCode <> 0 then
raise EThread.CreateResFmt(@SThreadCreateError, [SysErrorMessage(ErrCode)]);
{$ENDIF}
end;
← →
Digitman (2003-12-05 08:45) [8]
> почему Вы написали так, а не иначе
"жуткий вис" у тебя происходит по причине возникновения исключения в ходе исполнения тела метода Execute
это исключение ты никак не обрабатываешь
исключение связано с отсутствием синхронизации обращений код.потока к визуальным VCL-объектам с осн.код.потоком
обработчик события TThread.OnTerminate, если он назначен, выполняется как раз в контексте осн.потока, поэтому обращения в нем к VCL-объектам безопасно
← →
DeScriptor (2003-12-05 08:53) [9]2Digitman
А-а-а-а-а! Вот оно как!... Все-таки мне еще:
repeat
if not Научен then Учиться;
until Научен;
=)
Огромущее спасибо!
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.12.16;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.008 c