Форум программистов, компьютерный форум, киберфорум
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.80/25: Рейтинг темы: голосов - 25, средняя оценка - 4.80
52 / 5 / 1
Регистрация: 11.09.2018
Сообщений: 324

Как запустить несколько потоков одновременно?

21.12.2020, 21:27. Показов 6360. Ответов 43
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Ребята, здравствуйте.

Помогите с потоками. Я ранее использовал их лишь раз, чтобы сделать фоновую анимацию во время долгого процесса. Там не было ничего сложного.

Сейчас я хочу ускорить работу программы. Мне одной процедурой нужно обработать множество файлов. Файлы однотипны и пронумерованы. Т. е. 1.xml, 2.xml и т.д. Файлов может быть много, до 5000. Так вот, я хочу запустить потоков 10.
Что сейчас.

Так объявлен класс потока

Delphi
1
2
3
4
5
6
7
8
9
TNewThread = class(TThread)
  private
    { Private declarations }
   FileCount: Integer;
   LastSym: integer;         //переменные, которые передаю в метод потока
   procedure UpdateCaption;
  protected
   procedure Execute; override;
  end;
Далее в процедуре запуска (пока только 2 потока)

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
 NewThread: array[1..2] of TNewThread;
...
 
for i:=1 to 2 do
 begin
  NewThread[i]:=TNewThread.Create(true);
  NewThread[i].FileCount:= FileCount;
  NewThread[i].LastSym:=i;
  NewThread[i].FreeOnTerminate:=true;
  NewThread[i].Resume;
  NewThread[i].Priority:=tpNormal;
 end;
И реализация метода

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
{ TNewThread }
 
procedure TNewThread.UpdateCaption;
var
k, i: integer;
str_k: string;
xml, s: string;
 
begin
 for k:= 1 to FileCount  do
  begin
   str_k:= IntToStr(k);
   if str_k[length(str_k)] <> IntToStr(LastSym) then Continue;
 
   //Обрабатываем файлы процедурой Spisok
   if LastSym = 1 then Form1.Label1.Caption:= 'Обрабатываем файл '+ IntToStr(k) +' из '+IntToStr(FileCount);
   if LastSym = 2 then Form1.Label2.Caption:= 'Обрабатываем файл '+ IntToStr(k) +' из '+IntToStr(FileCount);
 
   Application.ProcessMessages;
   sleep(100);
 
   if LastSym = 1 then Form9.mmo1.Lines.LoadFromFile(ExtractFilePath(Application.ExeName)+ 'temp\'+IntToStr(k)+'.xml', TEncoding.UTF8);
   if LastSym = 2 then Form9.mmo2.Lines.LoadFromFile(ExtractFilePath(Application.ExeName)+ 'temp\'+IntToStr(k)+'.xml', TEncoding.UTF8);
 
   if LastSym = 1 then xml:= Form9.mmo1.Text;
   if LastSym = 2 then xml:= Form9.mmo2.Text;
 
   Spisok(xml);  //та самая ресурсная процедура, формирующая динамический список
 
   curr:=head;
   s:='';
   while Curr<>nil do
    begin
     for i:=1 to length(curr^.aff) do s:= s + Trim(curr^.aff[i-1])+'`';
     s:=s+#13#10;
     curr:=curr^.next;
    end;
 
 
       //выводим файл в csv
    if LastSym = 1 then Form1.Label1.Caption:= 'Выводим в csv файл '+ IntToStr(k) +' из '+IntToStr(FileCount);
    if LastSym = 2 then Form1.Label2.Caption:= 'Выводим в csv файл '+ IntToStr(k) +' из '+IntToStr(FileCount);
 
    sleep(100);
 
   if LastSym = 1 then
     begin
      Form9.mmo1.Text:= s;
      Form9.mmo1.Lines.SaveToFile(ExtractFilePath(Application.ExeName)+ 'result\'+IntToStr(k)+'.xml', TEncoding.UTF8);
     end;
 
   if LastSym = 2 then
     begin
      Form9.mmo2.Text:= s;
      Form9.mmo2.Lines.SaveToFile(ExtractFilePath(Application.ExeName)+ 'result\'+IntToStr(k)+'.xml', TEncoding.UTF8);
     end;
 
  end;
 
end;
 
procedure TNewThread.Execute;
begin
 Synchronize(UpdateCaption);
end;
Вроде все работает, но потоки выполняются один за другим, а мне нужно, чтобы одновременно.

Пробовал убирать синхронизацию, программа просто зависает. ничего не происходит.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
21.12.2020, 21:27
Ответы с готовыми решениями:

Как запустить несколько потоков с общим List?
Тема затертая до дыр, но которую я не могу понять вообще, тупо не поддается моему осознанию, задача проста: создать к примеру 3 потока,...

Как запустить несколько проектов одновременно?
Есть проект с готовыми (сохранёнными в собственной библиотеке) решениями. Надо куски кода из них скопировать в другой проект. Пока я...

Как запустить одновременно несколько форм в Lazarus'e?
Добрый день,возник такой вопрос: как запустить несколько форм одновременно?Вот,например,я создал несколько форм,при запуске выводится...

43
52 / 5 / 1
Регистрация: 11.09.2018
Сообщений: 324
24.12.2020, 11:45  [ТС]
Студворк — интернет-сервис помощи студентам


Не поверишь! Я уже на нее переделал!
0
Модератор
4150 / 2360 / 813
Регистрация: 15.11.2015
Сообщений: 9,489
24.12.2020, 12:10
Вы не поверите, но вот исходник StrToInt:
Delphi
1
2
3
4
5
6
7
function StrToInt(const S: string): Integer;
var
  E: Integer;
begin
  Val(S, Result, E);
  if E <> 0 then ConvertErrorFmt(@SInvalidInteger, [S]);
end;
0
52 / 5 / 1
Регистрация: 11.09.2018
Сообщений: 324
24.12.2020, 12:35  [ТС]
Тем не менее, с процедурой Val потоки работают!
0
 Аватар для mr-Crocodile
3053 / 1672 / 657
Регистрация: 19.03.2019
Сообщений: 5,380
24.12.2020, 13:48
Цитата Сообщение от AzAtom Посмотреть сообщение
Вы не поверите, но вот исходник StrToInt:
Разве в современных версиях (Rad Studio 10, например) так?
Там же точно должны региональные установки влиять!
и DecimalSeparator
StrToFloat

Description
Converts a given string to a floating-point value.

Use StrToFloat to convert a string, S, to a floating-point value (leading and trailing blanks are ignored).

S must consist of an optional sign (+ or -), a string of digits with an optional decimal point, and an optional mantissa.
The mantissa consists of 'E' or 'e' followed by an optional sign (+ or -) and an optional number.
The DecimalSeparator global variable or its TFormatSettings equivalent defines the character that is used as a decimal point. Thousand separators and currency symbols are not allowed in the string. If S does not contain a valid value, StrToFloat raises an EConvertError exception.

The first form of StrToFloat is not thread-safe, because it uses localization information contained in global variables. The second form of StrToFloat, which is thread-safe, refers to localization information contained in the AFormatSettings parameter. Before calling the thread-safe form of StrToFloat, you must populate AFormatSettings with localization information. To populate AFormatSettings with a set of default locale values, call TFormatSettings.Create.
впрочем, эту цитату здесь уже приводили...
0
Модератор
4150 / 2360 / 813
Регистрация: 15.11.2015
Сообщений: 9,489
24.12.2020, 14:07
Цитата Сообщение от mr-Crocodile Посмотреть сообщение
Разве в современных версиях (Rad Studio 10, например) так?
В XE3 точно так же.

Цитата Сообщение от mr-Crocodile Посмотреть сообщение
StrToFloat
StrToFloat по другому реализован, я за него и не писал.
1
 Аватар для mr-Crocodile
3053 / 1672 / 657
Регистрация: 19.03.2019
Сообщений: 5,380
24.12.2020, 14:09
AzAtom, ну да, для преобразования записи целого числа ничего дополнительно не нужно, в отличие от преобразования вещественного.
0
Модератор
4150 / 2360 / 813
Регистрация: 15.11.2015
Сообщений: 9,489
24.12.2020, 14:30
StrToFloat сделан на асме и реализация в XE3 мало чем отличается от реализации в D7.
0
 Аватар для mr-Crocodile
3053 / 1672 / 657
Регистрация: 19.03.2019
Сообщений: 5,380
24.12.2020, 15:20
Цитата Сообщение от AzAtom Посмотреть сообщение
StrToFloat сделан на асме и реализация в XE3 мало чем отличается от реализации в D7.
первая форма (The first form of StrToFloat is not thread-safe,) или вторая ( The second form of StrToFloat, which is thread-safe, refers to localization information contained in the AFormatSettings) ?
0
Модератор
4150 / 2360 / 813
Регистрация: 15.11.2015
Сообщений: 9,489
24.12.2020, 16:11
Цитата Сообщение от mr-Crocodile Посмотреть сообщение
первая форма (The first form of StrToFloat is not thread-safe,) или вторая
Это из XE3:
Delphi
1
2
3
4
function TextToFloat(const S: string; var Value: Extended): Boolean;
begin
  Result := TextToFloat(S, Value, FormatSettings);
end;
Насколько я понял, первая форма не является потокобезопасной потому, что пользуется дельфийский FormatSettings. А если пользоваться второй формой, то надо создать свою копию с FormatSettings, и тогда будет потокобезопасно.
А в итоге вызывается одна и та же функция TextToFloat, которая собственно и выполняет преобразования и написана на асме. То есть, дело не в функции преобразования.

Не по теме:

В общем, в предыдущем сообщении я неправильно выразился, что может ввести в заблуждение.

1
5 / 5 / 1
Регистрация: 09.12.2020
Сообщений: 194
24.12.2020, 18:21
Во всех языках есть разделение кода командой Inline;

Delphi
1
2
3
4
procedure MyProc(x:Integer); inline;
begin
    // …
end;
Это означает, что не используется 1 копия кода, а их несколько и каждый поток использует свою копию, хотя они все одинаковые. Размер программы конечно увеличивается за счет нескольких копий. Именно так и распараллеливают процессы.
0
 Аватар для krapotkin
6851 / 4677 / 1465
Регистрация: 14.04.2014
Сообщений: 20,676
Записей в блоге: 21
26.12.2020, 16:05
ох, сказочники...

Добавлено через 1 минуту
Delphi
1
2
3
4
5
6
var
 FS: TFormatSettings;
begin
  FS:=TFormatSettings.Create;
  price:= StrToFloat(st_price, fs);
end;
должно быть примерно так
0
52 / 5 / 1
Регистрация: 11.09.2018
Сообщений: 324
28.12.2020, 13:06  [ТС]
Пробовал так. Не помогло. впрочем процедура Val данную проблему решила. Однако мои "мучения" еще не окончены.

Теперь мне нужно в потоках заполнить файлы Excel. Сейчас они просто подвисают. Код такой.

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
var
k, i: integer;
str_k: string;
xml, s: array[0..9] of string;
t: array[0..9] of TStringlist;
 
Ex, Sheet: array[0..9] of Variant;
 
begin
 for k:= 1 to FileCount  do
  begin
   Application.ProcessMessages;
 
   str_k:= IntToStr(k);
   if str_k[length(str_k)] <> IntToStr(LastSym) then Continue;
 
   ...
 
  
   CopyFile(PChar(ExtractFilePath(Application.ExeName)+'templtate\templtate.xlsx'),   
PChar(ExtractFilePath(Application.ExeName)+'result\'+Filename+ '_' + IntToStr(k) + '.xlsx'), false); //Это единственное, что работает в потоках, если остальное закомментировать
 
   Ex[LastSym]:=CreateOleObject('Excel.Application');
   Ex[LastSym].DisplayAlerts:=False;   //отключаем предупреждения Excel о сохранении
   Ex[LastSym].Workbooks.Open(ExtractFilePath(ExtractFilePath(Application.ExeName)+'result\'+Filename+ '_' + IntToStr(k) + '.xlsx'));
   Sheet[LastSym]:=Ex[LastSym].Workbooks[ExtractFilePath(Application.ExeName)+'result\'+Filename+ '_' + IntToStr(k) + '.xlsx'].ActiveSheet;
 
   for i:=0 to High(templ) do Sheet[LastSym].Cells[1, i+1]:=templ[i, 1]; //шапка таблицы
 
    //закрываем, сохранив изменения
     Ex[LastSym].ActiveWorkbook.Close(True);
     //Ex[LastSym].Visible:=True;
     Ex[LastSym].Quit;
     Ex[LastSym]:=UnAssigned;
     Sheet[LastSym]:=Unassigned;
 
  end;
Все это метод Execute для потоков

Пробовал создавать переменную Ex как глобальную и CreateOleObject делать до вызова потоков. тоже все висело. как правильно?
0
Модератор
4150 / 2360 / 813
Регистрация: 15.11.2015
Сообщений: 9,489
28.12.2020, 14:08
Цитата Сообщение от Artiom-1984 Посмотреть сообщение
Application.ProcessMessages;
А что в потоке делает эта красота?
0
52 / 5 / 1
Регистрация: 11.09.2018
Сообщений: 324
28.12.2020, 15:15  [ТС]
Задержки sleep. У меня выводится контроль потоков. Я при копировании это удалил.

Добавлено через 43 минуты
Уже при

Ex[LastSym]:=CreateOleObject('Excel.Application');

потоки зависают.
0
Модератор
4150 / 2360 / 813
Регистрация: 15.11.2015
Сообщений: 9,489
28.12.2020, 16:06
Цитата Сообщение от Artiom-1984 Посмотреть сообщение
LastSym
Эта переменная чему равна? Где она инициализируется?
0
52 / 5 / 1
Регистрация: 11.09.2018
Сообщений: 324
28.12.2020, 16:27  [ТС]
Поле потока

Delphi
1
2
3
4
5
6
7
8
9
10
TExThread = class(TThread)
  private
    { Private declarations }
   FileCount: Integer;
   LastSym: integer;
   FileName: string;
 
  protected
   procedure Execute; override;
  end;
При запуске потоков

Delphi
1
2
3
4
5
6
7
8
9
10
 for i:=0 to 9 do
 begin
  ExThread[i]:=TExThread.Create(True);
  ExThread[i].FileCount:= FileCount;
  ExThread[i].FileName:= FileName;
  ExThread[i].LastSym:=i;
  ExThread[i].FreeOnTerminate:=true;
  ExThread[i].Priority:=tpNormal;
  ExThread[i].Resume;
 end;
0
Модератор
4150 / 2360 / 813
Регистрация: 15.11.2015
Сообщений: 9,489
28.12.2020, 16:42
Цитата Сообщение от Artiom-1984 Посмотреть сообщение
NewThread: array[1..2] of TNewThread;
Надо полагать, здесь переделано в
Delphi
1
NewThread: array[0..9] of TNewThread;
?
0
52 / 5 / 1
Регистрация: 11.09.2018
Сообщений: 324
28.12.2020, 19:50  [ТС]
Во-первых, разумеется, переделано, а во-вторых, это вообще другая процедура и другой класс потока.

По Excel кто-нибудь что-нибудь скажет?
0
Модератор
4150 / 2360 / 813
Регистрация: 15.11.2015
Сообщений: 9,489
28.12.2020, 20:02
Думаю, потоки тут ничего не ускорят потому, что скорость будет упираться в скорость обработки excel. В общем, смысла нет в потоках.
0
 Аватар для Пытливый
3764 / 2272 / 705
Регистрация: 29.05.2013
Сообщений: 9,622
29.12.2020, 02:09
Во первых, вам вообще нафик не нужен эксель для сохранения данных в табличном виде. Вполне достаточно сделать файл в формате .csv Эксель его чуть ли не родным считает и открывает без проблем.
Во вторых, для работы с Com-объектами из потока, нужно использовать пару функций CoInitialize и CoUnInitialize. Это тоже методы синхронизации, только с внешним миром.
В третьих, эксель и ворд всегда создают только один экземпляр в системе, поэтому CreateOleObject должен быть использован только один раз, а потом уже надо проверять, есть ли активный эксель и подключаться к нему через GetActiveOleObject. Обычно подключение делается так:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
try
  ExcelApp := GetActiveOleObject('Excel.Application');
 except
  try
   ExcelApp := CreateOleObject('Excel.Application');
  except on E: Exception
  do begin
     LogMessage('Не удалось запустить Excel!'#13#10 + E.Message, lgError);
     Exit;
     end;
  end;
 end;
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
29.12.2020, 02:09
Помогаю со студенческими работами здесь

Выполнение одновременно несколько sql запросов одновременно
Здравствуйте. Есть проблема! Пролистал много сайтов и форумов и толком ничего не нашел. Суть проблемы указана в заголовке но все равно...

Как запустить несколько потоков одновременно?
Здравствуйте, не могу решить проблему с объявлением количества потоков, нужно чтобы запускалось сразу (например) 20 потоков. Вот код...

Как запустить несколько потоков чтения/записи одновременно?
Делаю загрузку файлов на сервер. Хочу использовать потоки. Я попытался кое-что сделать: //FileSystem handler library var log =...

Создать и запустить одновременно несколько потоков
Всем привет) Необходимо создать несколько потоков и запустить их одновременно (без помощи циклов). Как это сделать? Помогите...

Как запустить несколько while одновременно?
Как запустить несколько while одновременно?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
19. здоровье, усталость и психотип работника влияют на производительность предприятия, и наоборот, производительность на здоровье, усталось и психотип
anaschu 28.05.2026
Дискретно-событийная модель рабочего коллектива на AnyLogic: здоровье, выгорание, психотипы и микростимуляция Привет, коллеги. Хочу поделиться итогами нескольких недель работы над симуляционной. . .
"Прокси" для последовательного порта
Eddy_Em 28.05.2026
Эту штуку написал я достаточно давно. Но сейчас вот понадобилось настроить датчик грозы, но при этом не отключать его от "метеодемона". Соответственно, надо запустить этот "прокси": метеодемон будет. . .
Рефакторинг программы уравнивания.
Massaraksh7 26.05.2026
Пример по предыдущей записи в блоге. Но, надо заметить, что, во-первых, там оптимизация не только математики, но и работы с базой данных, и с графами, а во-вторых, это ещё не всё.
Использование TThread в Lazarus для математических вычислений.
Massaraksh7 25.05.2026
Производя рефакторинг своих программ на предмет ускорения их работы, обратил внимание на такой аспект, как сокращение времени матвычислений. Дело в том, что приходится работать с большими матрицами. . .
Модель здравосохранения 18. Чем здоровее работник, тем быстрее выгорает
anaschu 24.05.2026
Имитационная модель корпоративного здравоохранения: что показывает математика Сегодня в модели рабочего коллектива на AnyLogic появились три новые механики — выгорание через накопленную усталость,. . .
Модель здравосохранения 17. Планы на выгорание
anaschu 23.05.2026
Вот конкретная схема реализации: В классе Работник добавить: накопленнаяУсталость — растёт каждый час работы, снижается в перерывы и болезни коэффициентПрезентеизма — снижает продуктивность. . .
Изменение цветов в палитре gif файла aka фавикона
russiannick 23.05.2026
Изменение цветов в палитре gif файла, юзаемого как фавиконка в составе html-файла, помещенная в base64, средствами нативного Java Script, навеянное сном в майский день. Для работы необходим браузер,. . .
Модель здравосохранения 16. Слишком хорошие и здоровые сотрудники уходят, недовольные зарплатой
anaschu 23.05.2026
Отладка увольнений и настройка производительности Сегодня во второй половине дня разобрались с механикой увольнений и настроили коэффициент сложности заданий. Вот что было сделано. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru