Не могли бы вы помочь мне, пожалуйста. Я пишу компонент (что-то вроде TListView), в моем компоненте я выполняю 3 процедуры по одной:
procedure findFiles(Path:String); // using FindFirst, FindNext
procedure ArrangeItems; // assigns Item Position
procedure SetIcons; // Loads Images, resizes, adds to ImageList
Я не могу понять, как заставить мой компонент использовать потоки для выполнения всех этих процедур, по крайней мере, первой (findFiles). Я пробовал разные способы, но ничего не выходит.
Вот пример того, что у меня есть (просто базовый пример).
type
TSearchThread = class(TThread)
private
SIView: TSIView;
protected
procedure Execute; override;
procedure DoSearch;
public
constructor Create(fSIView: TSIView);
end;
constructor TSearchThread.Create(fSIView: TSIView);
begin
SIView := fSIView;
FreeOnTerminate := True;
inherited Create(False);
Priority := tpLower;
end;
procedure TSearchThread.Execute;
begin
inherited;
Synchronize(DoSearch);
end;
first I tried to perform
SIView.findFiles('C:\');
ArrangeItems;
и только затем выполнить поток для установки соответствующих значков (SetIcons):
procedure TSearchThread.DoSearch;
begin
SetIcons;
end;
Это работало, но с ошибками: иногда мой компонент создавал иконки не для всех элементов, иногда некоторые элементы имели значки, полностью заполненные черным цветом, а иногда у меня вообще не было значков;
тогда я решил выполнить все 3 процедуры в теме:
procedure TSearchThread.DoSearch;
begin
SIView.findFiles('C:\');
ArrangeItems;
SetIcons;
end;
В результате у меня были те же ошибки при создании значков, и вместо поиска в указанной папке он искал в папке, где находилось мое приложение.
Чтобы вы поняли меня больше, я пытаюсь написать файловый менеджер с несколькими вкладками, поэтому, насколько я понимаю, мне нужно использовать потоки, чтобы приложение не зависало при работе с несколькими вкладками.
Не могли бы вы мне помочь, пожалуйста, чтобы понять, как организовать мой код? !!!!
Может быть, вы могли бы привести пример, потому что там не так много документации, касающейся потоков.
Привет еще раз.
Я пробовал оба AsyncCalls и OmniThreadLibrary. У них обоих был пример «фонового» поиска файлов. Сначала я обнаружил, что AsyncCalls больше подходит для моего приложения, поскольку оно действительно хорошо справилось со своей задачей. Я использовал AsyncCalls для выполнения моих трех процедур, и это было то, что я искал.
Я также попытался вызвать мои процедуры, используя OmniThreadLibrary, но казалось, что они не были выполнены в потоке.
Вот почему я предпочел AsyncCalls, но у меня есть вопрос, КАК ОСТАНОВИТЬ IAsyncCall, когда он работает?
Я имею в виду, например, как я уже упоминал до того, как мое приложение является многозадачным, и если пользователь открывает 3 вкладки и на каждой вкладке выполняет поиск файлов, то как мне остановить поиск файлов на второй вкладке?
Чтобы вам было проще понять, что я хочу сделать, вот набросок:
Форма имеет 3 TMemo, 3 TButton
var
a1, a2, a3: IAsyncCall;
procedure TForm1.Search(Path:String; MEMO:TMemo);
begin
/////// Finds files and adds to MEMO
end;
Все три кнопки работают одинаково, за исключением того, что они указывают на разные TMemo (Memo1, Memo2, Memo3);
procedure TForm1.Button1Click(Sender: TObject);
procedure DoSearch;
begin
Search('C:\', Memo1);
end;
begin
a1 := LocalAsyncCall(@DoSearch);
while AsyncMultiSync([a1], True, 0) = WAIT_TIMEOUT do
Application.ProcessMessages;
end;
Итак, если я нажму все три кнопки, у меня будет запущено 3 IAsyncCall. Как остановить любого из них, пока он еще работает?