Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.009 c
3-52101
Cat
2003-11-24 12:26
2003.12.16
На сервере-таблица, клиенту нужно к ней подключиться, нужен путь


3-52063
GIL
2003-11-25 12:29
2003.12.16
Очистка поля


4-52446
Vi0let
2003-10-23 03:28
2003.12.16
Отследить изменение разрешения экрана


3-52110
softmaster
2003-11-23 10:17
2003.12.16
Станность с БД


14-52378
bandera
2003-11-22 12:19
2003.12.16
FineReader 6.0 + Ошибка!





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский