52 / 5 / 1
Регистрация: 11.09.2018
Сообщений: 324

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

21.12.2020, 21:27. Показов 6511. Ответов 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
Модератор
4153 / 2362 / 814
Регистрация: 15.11.2015
Сообщений: 9,496
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
3054 / 1673 / 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
Модератор
4153 / 2362 / 814
Регистрация: 15.11.2015
Сообщений: 9,496
24.12.2020, 14:07
Цитата Сообщение от mr-Crocodile Посмотреть сообщение
Разве в современных версиях (Rad Studio 10, например) так?
В XE3 точно так же.

Цитата Сообщение от mr-Crocodile Посмотреть сообщение
StrToFloat
StrToFloat по другому реализован, я за него и не писал.
1
 Аватар для mr-Crocodile
3054 / 1673 / 657
Регистрация: 19.03.2019
Сообщений: 5,380
24.12.2020, 14:09
AzAtom, ну да, для преобразования записи целого числа ничего дополнительно не нужно, в отличие от преобразования вещественного.
0
Модератор
4153 / 2362 / 814
Регистрация: 15.11.2015
Сообщений: 9,496
24.12.2020, 14:30
StrToFloat сделан на асме и реализация в XE3 мало чем отличается от реализации в D7.
0
 Аватар для mr-Crocodile
3054 / 1673 / 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
Модератор
4153 / 2362 / 814
Регистрация: 15.11.2015
Сообщений: 9,496
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
6854 / 4680 / 1465
Регистрация: 14.04.2014
Сообщений: 20,684
Записей в блоге: 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
Модератор
4153 / 2362 / 814
Регистрация: 15.11.2015
Сообщений: 9,496
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
Модератор
4153 / 2362 / 814
Регистрация: 15.11.2015
Сообщений: 9,496
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
Модератор
4153 / 2362 / 814
Регистрация: 15.11.2015
Сообщений: 9,496
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
Модератор
4153 / 2362 / 814
Регистрация: 15.11.2015
Сообщений: 9,496
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
Ответ Создать тему
Опции темы

Новые блоги и статьи
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
[EasyBuilder Pro] Памятка по разработке для панелей Weintek
ФедосеевПавел 26.08.2026
Памятка по разработке для панелей Weintek ВВЕДЕНИЕ Ранее, при реализации проектов основное внимание уделял разработке управляющей программы для контроллера, а панели оператора доставалось время. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru