IPB
ЛогинПароль:

> Внимание!

1. Пользуйтесь тегами кода. - [code] ... [/code]
2. Точно указывайте язык, название и версию компилятора (интерпретатора).
3. Название темы должно быть информативным.
В описании темы указываем язык!!!

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

 
 Ответить  Открыть новую тему 
> CreateThread и _beginthreadex для gcc (minGw)
сообщение
Сообщение #1


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


Проблема вот в чем : в функциях win32api CreateThread и _beginthreadex как параметр функции-потока передается указатель на void. Для bcw 5.5 подойдет любой параметр,а вот gcc выдает ошибку о неправильном использовании void-параметра. Как обойти?переносить код на borland c++ 5.5 времени нет, да и исправлять всё там муторно.. в VS08 этот проект так же не переноситься..как быть?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гость






Показывай описание функции потока, и то, как ты пытаешься вызвать CreateThread

Сообщение отредактировано: volvo -
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


ну, допустим, вот пример простой :
#include <iostream>
#include <string>
#include <windows.h>



void prf(int i)
{
std::cout << i;
}


int main(int argc, char* argv[])
{
int i;
HANDLE ITT;
DWORD ID;
ITT=CreateThread(NULL,0,prf,&i,CREATE_SUSPENDED,&ID);
}


Ошибки :

initializing argument 3 of `void* CreateThread(_SECURITY_ATTRIBUTES*, DWORD, DWORD (*)(void*), void*, DWORD, DWORD*)'
invalid conversion from `void (*)(int)' to `DWORD (*)(void*)'
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гость






Ну, вот тебе пример вызова, который компилируется без ошибок:

#include <iostream>
#include <string>
#include <windows.h>

void prf(int i)
{
std::cout << i;
}

int main(int argc, char* argv[])
{
int i;
HANDLE ITT;
DWORD ID;
ITT=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)prf,&i,CREATE_SUSPENDED,&ID);
}

Вопрос в том, будет ли он правильно работать. Все-таки ты должен был делать
void prf(int* i)
, требуется же указатель, а не что-то другое...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


с этим понятно. Интересно, как же я бы сам смог до такого дойти, с нашими институтскими методичками.Спасибо большое. Только теперь другой вопрос :
вот такой вот код :

void prf( std::string fname)
{
std::cout << fname;
}


int main(int argc, char* argv[])
{
std::string fname="file";
HANDLE ITT[6];
DWORD ID;
for(int i=0;i<5;i++)
ITT[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)prf,&fname,0,&ID);

}


Куда проподает последний вызов?Точнее нет, он не проподает, я знаю. (если в конце поставить 2 cin.get(), то его можно увидеть после считывания символов), но все же, почему же 4 вызова происходят в один момент времени, а последний, 5ый, можно сказать "после завершения программы". Кстате, если использовать параметр функции потока как std::string* то вообще ничего не происходит. volvo, пожалуйста, разъясни ситиацию, я уже совсем ничего не понимаю.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Гость






Цитата
как же я бы сам смог до такого дойти, с нашими институтскими методичками

У тебя ж выход в Сеть есть? А в MSDN явно сказано, что третий параметр у CreateThread Function имеет тип LPTHREAD_START_ROUTINE... А если компилятор не может привести типы сам, надо попытаться ему помочь, в большинстве случаев это срабатывает.

Цитата
почему же 4 вызова происходят в один момент времени, а последний, 5ый, можно сказать "после завершения программы"
То есть, ты на 100% уверен, что запаздывает именно пятый поток? smile.gif Мне очень жаль тебя огорчать, конечно, но это не так... Смотри:
#include <iostream>
#include <string>
#include <windows.h>

void prf( std::string fname)
{
std::cout << fname;
}

int main(int argc, char* argv[])
{
std::string fname="file";
HANDLE ITT[6];
DWORD ID;
for(int i=0;i<5;i++) {
std::string s = fname + (char)(i + '0');
ITT[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)prf,&s,0,&ID);
}

}

Так какой поток запаздывает, говоришь? smile.gif А все потому, что передал-то я адрес переменной, но чему она равна в тот момент, когда начинает работать поток, и существует ли она вообще? При всем этом я и получать должен адрес, а не что-то иное... Кстати, еще одно: поток не завершается потому, что для гарантированного завершения функция prf должна вернуть значение. У тебя это невозможно, поскольку описана функция как void, а ведь MSDN предупреждает:
Цитата
Do not declare this callback function with a void return type and cast the function pointer to LPTHREAD_START_ROUTINE when creating the thread. Code that does this is common, but it can crash on 64-bit Windows.
( отсюда: ThreadProc Callback Function )

Вот так надо было делать, чтобы правильно отработали все потоки:
#include <iostream>
#include <string>
#include <windows.h>

DWORD prf(std::string *s)
{
std::cout << *s << std::endl;
return 0;
}


int main(int argc, char* argv[])
{
std::string fname="file";
HANDLE ITT[5]; // Зачем у тебя здесь было 6?

std::string strs[5]; // !!!
DWORD ID;
for(int i=0;i<5;i++) {
strs[i] = fname + (char)(i + '0'); // !!!
ITT[i] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)prf,&strs[i],0,&ID);
}
WaitForMultipleObjects(5, ITT, TRUE, INFINITE); // ждем завершения всех потоков
return 0;
}
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


Спасибо, volvo.. После этого поста, я думаю у тебя появиться желание меня убитьsmile.gif) Вообщем, код исходный :
main

#include "interface.h"

int main(int argc, char *argv[])
{
DWORD id[10];
HANDLE TH[10];
clock_t tS, tE;
std::vector<std::string> Paths;
tS=clock();
GetFileList(argv, Paths);
for (int i = 0; i < atoi(argv[2]); i++)
TH[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) MainFunction,
&Paths[i], 0, &id[i]);
WaitForMultipleObjects(atoi(argv[2]), TH, TRUE, INFINITE);
tE=clock();
return 0;
}




interface.h

#include <algorithm>
#include <iostream.h>
#include <process.h>
#include <windows.h>
#include <fstream.h>
#include <string>
#include <vector.h>
std::string GetStringFromFile(std::string &fname);
void GetFileList(char *argv[], std::vector<std::string>& vect);// Получает список файлов по заданной маске
std::string Parser(std::string &s, char& devider);
unsigned int GetDividerCount(std::string &s, char& devider);
bool comp(std::string s1, std::string s2);
std::string NameGenerator(char *argv[]);
void SaveResults (std::vector<std::string> &PS,std::size_t &parsedst);//changed
bool MainFunction(std::string *v);



realiz.cpp

#include "interface.h"
std::string GetStringFromFile(std::string &fname)//changed
{
std::string xstr;
std::ifstream xfile;
xfile.open(fname.data(), std::ios::binary);
xfile.seekg(0, std::ios_base::end);
xstr.resize(xfile.tellg());
xfile.seekg(0, std::ios_base::beg);
//копируем данные
char mychar[xstr.size()];
xfile.read(mychar, xstr.size());
xfile.close();
xstr = mychar;
return xstr;
}

void GetFileList(char *argv[], std::vector<std::string>& vect)//not changed
{
WIN32_FIND_DATA dFile;
HANDLE hFile;
std::string path;

char s[MAX_PATH] = "";
lstrcpy(s, argv[1]);
path = s;
lstrcat(s, "\\*.txt");

path += "\\";
hFile = FindFirstFile(s, &dFile);
if (hFile != INVALID_HANDLE_VALUE)
{
do
{
vect.push_back(path + dFile.cFileName);
} while (FindNextFile(hFile, &dFile) != 0);
FindClose(hFile);
}
}

unsigned int GetDividerCount(std::string &s, char& devider)//not changed
{
int count = 0;
for (unsigned int i = 0; i < s.size(); i++)
if (s.at(i) == devider)
count++;
return count;
}

std::string Parser(std::string &s, char& devider)//not changed
{
std::string bufs;
int n = s.find('.');
bufs.append(s, 0, n);
s.erase(0, n + 1);
return bufs;
}

bool comp(std::string s1, std::string s2)//not changed
{
return s1.size() > s2.size();
}

std::string NameGenerator(char *argv[])//not changed
{
std::string fname = "Result_____.txt";
SYSTEMTIME st;
GetSystemTime(&st);
fname.insert(7, argv[2]);
char ch[3];
itoa(st.wHour + 3, ch, 10);
if (fname.size() == 17)
fname.insert(10, ch);
else
fname.insert(9, ch);
itoa(st.wMinute, ch, 10);
if (fname.size() == 19)
fname.insert(13, ch);
else
fname.insert(12, ch);
itoa(st.wSecond, ch, 10);
if (fname.size() == 21)
fname.insert(16, ch);
else
fname.insert(15, ch);
return fname;
}

void SaveResults(std::vector<std::string> &PS, std::size_t &parsedst)//changed

{
ofstream outfile("result.txt", std::ios::app);
outfile << "\nFive longest strings for file " << " : \n";
for (unsigned int i = 0; i < 5; i++)
outfile << i + 1 << " - " << PS[i] << "\n";
outfile << "\nTotal count of parsed strings for this file : " << parsedst
<< "\n";
outfile.close();
}

bool MainFunction(std::string *v)
{
std::string String;//целая строка из файла
std::vector<std::string> PS;// вектор разбитых строк
char d = '.';//разделитель предложений
std::size_t parsedst = 0;//кол-во обработанных строк
unsigned int dcount = 0;//кол-во разделителей в файле определяет кол-во предложений в файле.
String = GetStringFromFile(*v);
dcount = GetDividerCount(String, d);
for (unsigned int j = 0; j < dcount; j++)
PS.push_back(Parser(String, d));
std::sort(PS.begin(), PS.end(), comp);
parsedst = PS.size();
SaveResults(PS, parsedst);
return TRUE;
}


Запускается через командную строку, ввиде : prog.exe *ПУТЬ к папке с файлами формата txt* *кол-во файлов для обработки*
Например C:\some\pr.exe C:\1 10.
Программа читает файлы и создает результирующий файл, в котором записываются 5 самых длинных предложений для каждого файла. Предложения разделяются символом "." .
Прикладываю архив с файлами для обработки.
Проблема вот в чем, я раньше выкладывал этот код для одно-потокового варианта, сейчас надо организовать многопоточностьsmile.gif. Основная проблема в том, что в результирующем файл записываются результаты не для всех файлов. В принципе, это наверное из-за асинхронизации процессов. Необходимо использовать какие-либо средства для синхронизации?Ну, допустим, мьютексы. Я прав? Если нет , то в чем ошибка?

Сообщение отредактировано: Andrewshkovskii -


Прикрепленные файлы
Прикрепленный файл  1.zip ( 1.19 килобайт ) Кол-во скачиваний: 157
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Гость






Цитата
Необходимо использовать какие-либо средства для синхронизации?
Необходимо запрещать доступ к файлу, в который пишется информация, одновременно нескольким потокам... Проще всего - реализовать через Event-ы: в начале работы программы создаешь событие, которое будет контролировать доступ к файлу результатов:

HANDLE myEvent; // в H-файле эта переменная описана через extern

int main(int argc, char *argv[])
{
DWORD id[10] = {0};
HANDLE TH[10] = {0};
clock_t tS, tE;

myEvent = CreateEvent(NULL, FALSE, FALSE, NULL); // Создаем событие,
SetEvent(myEvent); // и сразу же его устанавливаем, чтоб не держать потоки

std::vector<std::string> Paths;
tS=clock();
GetFileList(argv, Paths);
for (int i = 0; i < atoi(argv[2]); i++) {
TH[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) MainFunction,
&Paths[i], 0, &id[i]);
}

WaitForMultipleObjects(atoi(argv[2]), TH, TRUE, INFINITE);
tE=clock();
return 0;
}

, а для того, чтобы гарантировать, что пока один поток пишет в файл, другой будет ждать освобождения файла, чуть-чуть меняешь функцию потока:
bool MainFunction(std::string *v)
{
std::string String; // целая строка из файла
std::vector<std::string> PS; // вектор разбитых строк
char d = '.'; // разделитель предложений
std::size_t parsedst = 0; // кол-во обработанных строк
unsigned int dcount = 0; // кол-во разделителей в файле определяет кол-во предложений в файле.
String = GetStringFromFile(*v);
dcount = GetDividerCount(String, d);
for (unsigned int j = 0; j < dcount; j++)
PS.push_back(Parser(String, d));
std::sort(PS.begin(), PS.end(), comp);
parsedst = PS.size();

WaitForSingleObject(myEvent, INFINITE); // если Event сброшен - ждать
SaveResults(PS, parsedst);
SetEvent(myEvent); // По окончании записи в файл разрешить записывать другим

return TRUE;
}
Вот и все, теперь информация от всех тредов будет сохранена...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


Внимание, вопрос :
SetEvent(myEvent); // и сразу же его устанавливаем, чтоб не держать потоки
for (int i = 0; i < atoi(argv[2]); i++){
TH[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) MainFunction,
&Paths[i], 0, &id[i]);//создаем потоки
SetThreadPriority(TH[i],THREAD_PRIORITY_HIGHEST);//изменяем приоритет созданного потока

Время исполнения не изменяется в лучшую сторону, а иногда даже ухудщается.. вот файл с тестами.
A - вариант с однопоточным.
B - вариант с многопоточным.
C - вариант с изменением приоритетов.
h - чтение с hdd
f - с flash.


Прикрепленные файлы
Прикрепленный файл  ____________________.xls ( 35 килобайт ) Кол-во скачиваний: 247
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Гость






Цитата
Время исполнения не изменяется в лучшую сторону, а иногда даже ухудщается..
Во-первых, как ты замерял время?

Во-вторых, кто тебе сказал, что при при изменении приоритета потока это изменение вообще влияет на скорость выполнения данного потока? Ну, допустим, у тебя поток теперь имеет THREAD_PRIORITY_HIGHEST. А сам процесс твой с каким приоритетом работает?

Дальше: ты работаешь с диском, а это уже медленно, имеет ли смысл повышать приоритет, чтоб работать с медленными устройствами? Кроме всего прочего, Windows сама прекрасно может динамически менять приоритет твоего потока (что может отрицательно сказаться на быстродействии приложения, были жалобы, об этом есть у Рихтера), именно по этой причине есть функции SetProcessPriorityBoost / SetThreadPriorityBoost

Ну, и напоследок...

Если уж ты действительно хочешь попробовать изменить приоритет потока, то создавай поток "спящим", потом меняй приоритет, и потом "буди" поток, так будет лучше.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


1 . Мне по заданию надо использовать функцию повышения приоритета , добившись тем самым , как написано " Заметного прироста скорости работы".
2 . Замеряю так :

int main(int argc, char *argv[])
{
if (argc < 3 || atoi(argv[2]) < 0 || atoi(argv[2]) == 0 || atoi(argv[2])
> 10)
{
cout << "Not enought parametrs of wrong file number parameter";
exit(0);
}
clock_t tS, tE;//Переменные для фиксации начала и конца обработки
tS = clock();
...
WaitForMultipleObjects(atoi(argv[2]), TH, TRUE, INFINITE);//ждем завершения всех потоком
tE = clock();
outfile << "\nTime elapsed : " << tE - tS << " miliseconds";
outfile.close();
return 0;
}

3. процесс работает с нормальным приоритетом . т.е normal class.
Насчет создания спящем..сейчас попробую

Сообщение отредактировано: Andrewshkovskii -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 30.11.2021 19:57
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name