12 / 12 / 9
Регистрация: 12.04.2012
Сообщений: 259
1

Создание потоков для работы со строками

05.06.2012, 17:35. Показов 3465. Ответов 10
Метки нет (Все метки)

Мне нужно много поточное приложение которое может отрыть текстовый файл и в разных потоках работать с этими строками но в каждом потоке должна быть своя строка то есть в первом потоке первая строка из листа в это время второй поток берет 2 строку а третий третью строку и.т.д .
Вот как я это реализовал
C++
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
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
#include "process.h"
TForm1 *Form1;
TStringList *Навход = new TStringList; // Стринг лист для загрузки файла
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if(Form1->OpenTextFileDialog1->Execute()){  //загрузка строк текстового файла
       Навход->LoadFromFile(Form1->OpenTextFileDialog1->FileName);
}
}
void Thread1(void *Param) { //Поток для работы
for(int i = 0; i < Навход->Count/3; i++){//Цикл бежит по строкам из Листа "Навход" от 0 до количества строк в Листе делить на 2 поскольку  у нас 4 потока)
Form1->Memo1->Lines->Add(Навход->Strings[i]); //Вывод в мемо поле строки из листа
}
 _endthread();
}
void Thread2(void *Param) { //Поток для работы
for(int i = Навход->Count/3; i < Навход->Count/2; i++){//Цикл бежит по строкам из Листа "Навход" количества строк в Листе делить на 2 поскольку у нас 4 потока до количество строк делить на 3 )
Form1->Memo1->Lines->Add(Навход->Strings[i]); //Вывод в мемо поле строки из листа
}
 _endthread();
}
void Thread3(void *Param) { //Поток для работы
for(int i = Навход->Count/2; i < Навход->Count; i++){//Цикл бежит по строкам из Листа "Навход" количества строк в Листе делить на 3 поскольку у нас 4 потока до количество строк в Листе)
Form1->Memo1->Lines->Add(Навход->Strings[i]); //Вывод в мемо поле строки из листа
}
_endthread();
}
/*
Таким образом мы смогли создать 3 потока которые идут по одному стринг листу
Но по разным строкам.
   */
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
_beginthread(Thread1, 0, (void*)(0));
_beginthread(Thread2, 0, (void*)(0));
_beginthread(Thread3, 0, (void*)(0));
}
//---------------------------------------------------------------------------
Но хотелось бы не три потока и описывать их каждый раз а столько потоков сколько допустим укажу в едит поле. И так какие вопросы как создать 50 или 100 потоков делающих одну функцию но с разными строками и не описывать каждый поток а то так код может из за 1000 строк перевалить если 100 потоков в ручную описывать что приведет к огромному размеру программы. Не понятно как в цикле создать потоки и передать им № потока ну для работы со строками ну или как то еще.
Прошу помогите если не понятно что я тут написал смотрите на код сверху.
Спасибо всем кто поможет.)
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.06.2012, 17:35
Ответы с готовыми решениями:

Создание класса для работы со строками
Помогите пжл написать программу: Создать класс для работы сo строками. Разработать следующие...

Создание собственной библиотеки функций для работы со строками
Здравствуйте, необходимо создать библиотеку, которая включает в себя несколько функции для работы...

Создание проекта с использованием компонентов для работы со строками и текстом
1) Разработать приложение, которое позволяет ввести текст в многострочный редактор и удалить из...

Создание отдельных потоков и работы с ними в Xamarin Forms
Добрый день, коллеги! Подскажите пожалуйста, желательно с примером кода, как в проектах Xamarin...

10
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
05.06.2012, 17:51 2
Самая главная ошибка: ты добавляешь строки в Мемо из других потоков без синхронизации.

2 ошибка: добавляешь текст построчно, вместо того, чтобы добавить целиком и запретить перерисовку

C++
1
2
3
    Memo1->Lines->BeginUpdate();
           Memo1->Lines->AddStrings(Навход);
    Memo1->Lines->EndUpdate();
Цитата Сообщение от leva Посмотреть сообщение
TStringList *Навход = new TStringList; // Стринг лист для загрузки файла
3 ошибка: здесь ты создаёшь объект, а где удаление этого объекта?
2
12 / 12 / 9
Регистрация: 12.04.2012
Сообщений: 259
05.06.2012, 18:42  [ТС] 3
Цитата Сообщение от Maluda Посмотреть сообщение
Самая главная ошибка: ты добавляешь строки в Мемо из других потоков без синхронизации.

2 ошибка: добавляешь текст построчно, вместо того, чтобы добавить целиком и запретить перерисовку

C++
1
2
3
    Memo1->Lines->BeginUpdate();
           Memo1->Lines->AddStrings(Навход);
    Memo1->Lines->EndUpdate();


3 ошибка: здесь ты создаёшь объект, а где удаление этого объекта?
Да про ошибки знаю мне тут главное узнать как потоки в цикле создать и не описывать каждый поток отдельно, а про мемо почему не льзя добавлять по строчно?
0
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
06.06.2012, 00:43 4
Цитата Сообщение от leva Посмотреть сообщение
про мемо почему не льзя добавлять по строчно?
Можно и построчно, но у тебя объект TStringList тремя разными потоками построчно добавляется в другой TStringList, который является членом класса TMemo и каждый раз при добавлении строки тратится время на перерисовку TMemo, поэтому, чтобы выиграть во времени (а я так понимаю, для тебя это главное), лучше заблокировать отрисовку контрола, затем единой транзакцией добавить все строки и потом разблокировать отрисовку. Я тебе гарантирую увеличение по скорости раз в десять.

Цитата Сообщение от leva Посмотреть сообщение
как потоки в цикле создать
Во-первых, если пользоваться потоками для того, чтобы из них обновлять VCL контролы, то, необходимо использовать VCL потоки TThread с вызовом метода Synchronize.

Во-вторых, если хочешь свои потоки в цикле создать, то в чём проблема?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
std::auto_ptr<TStringList>AMyList(new TStringList);
 
void ThreadFunc(void *Param) { 
        // получаем переменную переданную в текущий поток, 
        // в данном случае для примера - это ID нашего потока
    const int iParam = (int)Param;
 
        // выполняем какие-то действия в зависимости от ID потока
    AMyList->Add(iParam);
 
    _endthread();
}
 
 
//---------------------------------------------------------------------------
void __fastcall TForm2::btnMyClick(TObject *Sender) {
    // создадим 10 потоков и передадим им функцию с параметром равным индексу потока
        for (int i = 0; i < 10; i++) {
         _beginthread(ThreadFunc, 0, (void *)i);
    }
}
2
12 / 12 / 9
Регистрация: 12.04.2012
Сообщений: 259
06.06.2012, 22:41  [ТС] 5
Цитата Сообщение от Maluda Посмотреть сообщение
Можно и построчно, но у тебя объект TStringList тремя разными потоками построчно добавляется в другой TStringList, который является членом класса TMemo и каждый раз при добавлении строки тратится время на перерисовку TMemo, поэтому, чтобы выиграть во времени (а я так понимаю, для тебя это главное), лучше заблокировать отрисовку контрола, затем единой транзакцией добавить все строки и потом разблокировать отрисовку. Я тебе гарантирую увеличение по скорости раз в десять.


Во-первых, если пользоваться потоками для того, чтобы из них обновлять VCL контролы, то, необходимо использовать VCL потоки TThread с вызовом метода Synchronize.

Во-вторых, если хочешь свои потоки в цикле создать, то в чём проблема?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
std::auto_ptr<TStringList>AMyList(new TStringList);
 
void ThreadFunc(void *Param) { 
        // получаем переменную переданную в текущий поток, 
        // в данном случае для примера - это ID нашего потока
    const int iParam = (int)Param;
 
        // выполняем какие-то действия в зависимости от ID потока
    AMyList->Add(iParam);
 
    _endthread();
}
 
 
//---------------------------------------------------------------------------
void __fastcall TForm2::btnMyClick(TObject *Sender) {
    // создадим 10 потоков и передадим им функцию с параметром равным индексу потока
        for (int i = 0; i < 10; i++) {
         _beginthread(ThreadFunc, 0, (void *)i);
    }
}
Спасибо огромное, а если в стринг лист много потоков будут записывать строки, то все нормально будет? без вывода в мемо!
0
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
07.06.2012, 08:33 6
Цитата Сообщение от leva Посмотреть сообщение
если в стринг лист много потоков будут записывать строки, то все нормально будет?
Если список несортированный и строки добавляются в конец списка, то, думаю, да.
0
Эксперт С++
3950 / 1805 / 184
Регистрация: 21.11.2009
Сообщений: 2,540
07.06.2012, 10:54 7
Цитата Сообщение от Maluda Посмотреть сообщение
2 ошибка: добавляешь текст построчно, вместо того, чтобы добавить целиком и запретить перерисовку

C++
1
2
3
Memo1->Lines->BeginUpdate();
Memo1->Lines->AddStrings(Навход);
Memo1->Lines->EndUpdate();
Попробуйте проверить то, что советуете...
Метод AddStrings внутри себя вызывает вышеуказанные методы блокировок.
Если хотите выполнить загрузку большого количества строк быстрее - воспользуйтесь классом TMemoryStream.

Ну и для интереса, выполните такой тест:
C++
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
const int ItemsCount = 100000;
unsigned long Start, Stop;
int i;
TStringList *SList = new TStringList();
for (i = 0; i < ItemsCount; SList->Add("Line " + IntToStr(i)), i++);
 
//------ With BeginUpdate & EndUpdate methods ------
Memo1->Lines->BeginUpdate();
Start = GetTickCount();
for (i = 0; i < ItemsCount; Memo1->Lines->Add("Line " + IntToStr(i)), i++);
Stop = GetTickCount();
Memo1->Lines->EndUpdate();
Memo1->Clear();
ShowMessage(Stop - Start);
//--------------------------------------------------
 
//---------------- Only Add method -----------------
Start = GetTickCount();
for (i = 0; i < ItemsCount; Memo1->Lines->Add("Line " + IntToStr(i)), i++);
Stop = GetTickCount();
Memo1->Clear();
ShowMessage(Stop - Start);
//--------------------------------------------------
 
//------------ Only AddStrings method --------------
Start = GetTickCount();
Memo1->Lines->AddStrings(SList);
Stop = GetTickCount();
Memo1->Clear();
ShowMessage(Stop - Start);
//--------------------------------------------------
 
//---------- Loading from TMemoryStream ------------
TMemoryStream *MStream = new TMemoryStream();
MStream->Position = soFromBeginning;
SList->SaveToStream(MStream);
MStream->Position = soFromBeginning;
Start = GetTickCount();
Memo1->Lines->LoadFromStream(MStream);
Stop = GetTickCount();
Memo1->Clear();
ShowMessage(Stop - Start);
//--------------------------------------------------
 
delete MStream;
delete SList;
Результаты в Release-варианте должны быть примерно следующие:
14 212 мс. - добавление через Add, с методами BeginUpdate & EndUpdate.
12 730 мс. - добавление только через Add.
13 260 мс. - метод AddStrings.
2 668 мс. - TMemoryStream и LoadFromStream.
0
12 / 12 / 9
Регистрация: 12.04.2012
Сообщений: 259
07.06.2012, 11:39  [ТС] 8
Цитата Сообщение от MikeSoft Посмотреть сообщение
Попробуйте проверить то, что советуете...
Метод AddStrings внутри себя вызывает вышеуказанные методы блокировок.
Если хотите выполнить загрузку большого количества строк быстрее - воспользуйтесь классом TMemoryStream.

Ну и для интереса, выполните такой тест:
C++
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
const int ItemsCount = 100000;
unsigned long Start, Stop;
int i;
TStringList *SList = new TStringList();
for (i = 0; i < ItemsCount; SList->Add("Line " + IntToStr(i)), i++);
 
//------ With BeginUpdate & EndUpdate methods ------
Memo1->Lines->BeginUpdate();
Start = GetTickCount();
for (i = 0; i < ItemsCount; Memo1->Lines->Add("Line " + IntToStr(i)), i++);
Stop = GetTickCount();
Memo1->Lines->EndUpdate();
Memo1->Clear();
ShowMessage(Stop - Start);
//--------------------------------------------------
 
//---------------- Only Add method -----------------
Start = GetTickCount();
for (i = 0; i < ItemsCount; Memo1->Lines->Add("Line " + IntToStr(i)), i++);
Stop = GetTickCount();
Memo1->Clear();
ShowMessage(Stop - Start);
//--------------------------------------------------
 
//------------ Only AddStrings method --------------
Start = GetTickCount();
Memo1->Lines->AddStrings(SList);
Stop = GetTickCount();
Memo1->Clear();
ShowMessage(Stop - Start);
//--------------------------------------------------
 
//---------- Loading from TMemoryStream ------------
TMemoryStream *MStream = new TMemoryStream();
MStream->Position = soFromBeginning;
SList->SaveToStream(MStream);
MStream->Position = soFromBeginning;
Start = GetTickCount();
Memo1->Lines->LoadFromStream(MStream);
Stop = GetTickCount();
Memo1->Clear();
ShowMessage(Stop - Start);
//--------------------------------------------------
 
delete MStream;
delete SList;
Результаты в Release-варианте должны быть примерно следующие:
Отлично спасибо но я полностью отказался от вывода буду в текстовый файл строки записывать.
0
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
07.06.2012, 16:49 9
MikeSoft, я всегда проверяю, то что советую! Я абсолютно согласен с тем,
что через потоки быстрее, но в корне не согласен, что Add без BeginUpdate и EndUpdate быстрее??? AddStrings, как показано в ваших результатах. По моим результатам AddStrings быстрее в 7 раз! Прилагаю код, который проверял и параметры своей машины, на которой тестил:
Intel Core 2 Quad Q6600 2.4 GHz
CBuilder 2010
Windows XP Service Pack 3

П.С. К тому же, если внимательно посмотрите на код, который приложу ниже, то увидите,
что есть ещё один, наверное, лучший способ.
П.С.2 Отсчёт времени при измерении копирования потоком необходимо начать до объявления потока

C++
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
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender) {
    const int ItemsCount = 100000;
    unsigned long Start, Stop;
    int i;
    TStringList *SList = new TStringList();
    for (i = 0; i < ItemsCount; SList->Add("Line " + IntToStr(i)), i++);
 
    // ВОТ ТАК ДЕЛАЛОСЬ ДОБАВЛЕНИЕ У ПОЛЬЗОВАТЕЛЯ [B]leva[/B]
    //---------------- Only Add method -----------------
    Start = GetTickCount();
    for (i = 0; i < ItemsCount; Memo1->Lines->Add("Line " + IntToStr(i)), i++);
    Stop = GetTickCount();
 
    ShowMessage("Время добавления через Add - " + UnicodeString(Stop - Start));
 
    Memo1->Clear();
    //--------------------------------------------------
 
    // ВОТ ТАК ПОСОВЕТОВАЛ Я
    //------------ AddStrings method --------------
    Start = GetTickCount();
    Memo1->Lines->BeginUpdate();
    Memo1->Lines->AddStrings(SList);
    Memo1->Lines->EndUpdate();
    Stop = GetTickCount();
 
    ShowMessage("Время добавления через AddStrings - " + UnicodeString(Stop - Start));
 
    Memo1->Clear();
    //--------------------------------------------------
 
    //---------- Loading from TMemoryStream ------------
    Start = GetTickCount(); // ОТСЧЁТ НЕОБХОДИМО НАЧАТЬ ОТСЮДА
 
    TMemoryStream *MStream = new TMemoryStream();
    MStream->Position = soFromBeginning;
    SList->SaveToStream(MStream);
    MStream->Position = soFromBeginning;
    Memo1->Lines->LoadFromStream(MStream);
    delete MStream;
 
    Stop = GetTickCount();
 
    ShowMessage("Время добавления через TMemoryStream - " + UnicodeString(Stop - Start));
    Memo1->Clear();
 
    //---------- Ради интереса ------------
    Start = GetTickCount();
 
    Memo1->Lines->Text = SList->Text;
 
    Stop = GetTickCount();
    ShowMessage("Время добавления простым присваиванием - " + UnicodeString(Stop - Start));
    // --------------------------------------------------
 
    delete SList;
}
//---------------------------------------------------------------------------
Результы:
Add - 30.453 сек
AddStrings - 4.594 сек
TMemoryStream - 0.922 сек
Простое копирование - 0.906 сек
Миниатюры
Создание потоков для работы со строками   Создание потоков для работы со строками   Создание потоков для работы со строками  

Создание потоков для работы со строками  
0
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
07.06.2012, 16:57 10
MikeSoft, и самое главное ! Речь шла о добавлении строк а не о копировании всего текста! Вы каждый раз очищаете Memo!
А у пользователя Memo будет постепенно заполняться строками из открытого файла. Я не видел у него в коде при открытии файла очистку Memo.

Цитата Сообщение от leva Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if(Form1->OpenTextFileDialog1->Execute()){ //загрузка строк текстового файла
 Навход->LoadFromFile(Form1->OpenTextFileDialog1->FileName);
}
}
void Thread1(void *Param) { //Поток для работы
for(int i = 0; i < Навход->Count/3; i++){//Цикл бежит по строкам из Листа "Навход" от 0 до количества строк в Листе делить на 2 поскольку у нас 4 потока)
Form1->Memo1->Lines->Add(Навход->Strings[i]); //Вывод в мемо поле строки из листа
}
 _endthread();
}
0
12 / 12 / 9
Регистрация: 12.04.2012
Сообщений: 259
07.06.2012, 22:24  [ТС] 11
Помогите что с кодом вроде такой же как я выше писал, но все потоки тут же завершаются без ошибок
C++
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
//---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
 
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "sButton"
#pragma link "sMemo"
#pragma link "sEdit"
#pragma link "sDialogs"
#pragma resource "*.dfm"
#include "process.h"
#include <stdio.h>
TForm1 *Form1;
TStringList *AMyList= new TStringList;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
void ThreadFunc(void *Param) { //потоки для работы
    const int iParam = (int)Param;
TIdHTTP *httpsiParam= new TIdHTTP(0);
for(int i = AMyList->Count/StrToInt(Form1->sEdit1->Text)-1*iParam; i < AMyList->Count/StrToInt(Form1->sEdit1->Text)-1*iParam+1; i++){
try{
String mail=httpsiParam->Get("http://="+AMyList->Strings[i]);
if(mail.Pos("false")>0){
 Form1->sMemo1->Lines->Add(AMyList->Strings[i]) ;
}
}
catch(...){;}
}
//////////////////////////////////////////////////////////
    if(iParam==StrToInt(Form1->sEdit1->Text)){
    ShowError("Поток №"+Form1->sEdit1->Text+" завершон");
    }
    delete httpsiParam;
    _endthread();
}
void Thread1(void *Param) {// поток создания потоков)
 for (int i = 0; i < StrToInt(Form1->sEdit1->Text); i++) {//в  Edit1 количество потоков
  _beginthread(ThreadFunc, 0, (void *)i);
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::sButton1Click(TObject *Sender)
{
_beginthread(Thread1, 0, (void*)(0)); //создаем потоки
}
//---------------------------------------------------------------------------
void __fastcall TForm1::sButton2Click(TObject *Sender)
{
if(sOpenDialog1->Execute()){           // открыть текст файл в  AMyList
      AMyList->LoadFromFile(sOpenDialog1->FileName);
}
}
//---------------------------------------------------------------------------
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
07.06.2012, 22:24
Помогаю со студенческими работами здесь

Замедление работы потоков если запущено несколько потоков
Есть отдельный поток который движет красным квадратом. Он каждую миллисекунду меняет положение...

Функции для работы со строками в VB
Помогите со строками. Какие есть функции для обработки строк? В хелпе ничего разобрать не смог, а...

Алгоритм для работы со строками
Здравствуйте! Прошу помощи. Есть массив, в котором записан текст из текстового файла. Так вот,...

Разработка ПО для работы со строками
разработка ПО для работы со строками ..... по такой теме какие функции можно реализовать в...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru