Опять вопросы про _beginthreadex

vadipok
Дата: 07.10.2014 14:44:01
Добрый день, коллеги!

Нужна помощь!!
Создал структуру IPADDRESS, а потом прикрутил его в вектор ipAddress_vec.
Там где 111...1 я его заполняю.
Там где 222...2 пытаюсь его запустить функцию getDataCPU в нескольких потоках через _beginthreadex, в зависимости от того, сколько элементов в ipAddress_vec.
В функции getDataCPU происходит простой вывод на экран, и тут проблема становится очевидной.
Выводит на экран только последний элемент вектора для всех 3-х случаев.
(Смотри прин-скрин командной строки.)
Гугление не помогает.
Как быть? Что делать?

Спасибо большое!

Переменные:
struct IPADDRESS
{
	int   employeeID;
	char* ipAddress;
	int   step;
};

vector <IPADDRESS> ipAddress_vec;

IPADDRESS ipAddressStrucIn;
IPADDRESS ipAddressStrucOut;
IPADDRESS* ipAddressStruct = (IPADDRESS*)malloc(sizeof(IPADDRESS));


Кусок кода main:
		ResultSet *rs = stmt->executeQuery();
		while (rs->next())
			  {
			  ipAddressStrucIn.employeeID = rs->getInt (1);
			  t1  = rs->getInt (2);
			  t2  = rs->getInt (3);
			  t3  = rs->getInt (4);
			  t4  = rs->getInt (5);
			  ss << t1 << "." << t2 << "." << t3 << "." << t4;
			  t = ss.str();
			  ipAddressStrucIn.ipAddress = strdup(t.c_str());

			  ipAddress_vec.push_back(ipAddressStrucIn);

			  cout << ipAddressStrucIn.ipAddress << endl;
			  cout << ipAddressStrucIn.employeeID << endl;

			  //clear
			  ss.str(std::string());
			  ss.clear();
			  t.clear();
		  

			  }

		cout << "11111111111111111111111111111111" << endl;

		//const *int threadSize = (int) ipAddress_vec.size();

		HANDLE threads[1000];

		for (d=0;d<(int) ipAddress_vec.size();d++) {
			ipAddressStrucOut = ipAddress_vec[d];
			cout << "22222222222222222222222222222222" << endl;
			ipAddressStruct->employeeID = ipAddressStrucOut.employeeID;
			ipAddressStruct->ipAddress = ipAddressStrucOut.ipAddress;
			ipAddressStruct->step = d;

			threads[d] = (HANDLE)_beginthreadex(NULL,0,&getDataCPU, (void *) ipAddressStruct,0,NULL);
		}

		Sleep(5000);

		// пробовал, не помогло
		//WaitForMultipleObjects(1000, threads, true, INFINITE);

		for(d=0;d<ipAddress_vec.size();d++) {
			cout << "33333333333333333333333333333" << endl;
			WaitForSingleObject( threads[d], INFINITE );
			CloseHandle(threads[d]);
		}


getDataCPU:
unsigned __stdcall getDataCPU( void* pArguments )
{
	cout << "44444444444444444444444444444444" << endl;
	IPADDRESS *ipAddress2 = static_cast<IPADDRESS*>(pArguments);
	cout << ipAddress2->employeeID <<endl;
	cout << ipAddress2->ipAddress  <<endl;
	cout << ipAddress2->step  <<endl;
	cout << GetCurrentThreadId() << endl;
	_endthreadex( 0 );

    return 0;   // Program successfully completed.
}
Dima T
Дата: 07.10.2014 14:59:56
Классическая ошибка. Вызов:
_beginthreadex(NULL,0,&getDataCPU, (void *) ipAddressStruct,0,NULL);

не означает что выполнится и потом выйдет из beginthreadex() и пойдет дальше
IPADDRESS *ipAddress2 = static_cast<IPADDRESS*>(pArguments);


реально происходит так первый поток вызывает несколько раз beginthreadex(), а уже потом созданные потоки выполняют чтение pArguments, в котором первый поток видит то что предназначено не ему, а последующим.

PS Запутался в твоих указателях, как подправить не скажу, передавай в параметрах адрес структуры, а не адрес указателя на структуру.
Dima T
Дата: 07.10.2014 15:14:09
Помедитируй над этим кодом
unsigned __stdcall thread( void* pArguments )
{
	int j = *(int*)pArguments;
	printf("%d\n", j);
	_endthreadex( 0 );
    return 0;   // Program successfully completed.
}

int main( void )
{
	for(int i = 0; i < 4; i++)
	{
		_beginthreadex(NULL,0,&thread, (void *) &i,0,NULL);
		//Sleep(100);
	}
	Sleep(5000);
}


Попробуй Sleep(100); разремить
vadipok
Дата: 07.10.2014 15:20:11
Dima T,

На моем примере помогло, спасибо!

Но в реальном примере функция getDataCPU намного больше и работает для некоторых IP-ишников на порядок дольше(может быть до минуты).
Час попробую функцию getDataCPU вернуть в реальное состояние.
Dima T
Дата: 07.10.2014 15:28:18
vadipok
На моем примере помогло, спасибо!

Я у Sleep(100) поставил не для того чтобы ты его к себе скопипастил
Добейся чтоб мой пример работал корректно без слипа. Повторяю проблема в том что передается указатель на i, а в момент чтения по адресу этого указателя в i совсем другое значение.
vadipok
Дата: 07.10.2014 15:30:59
Dima T
vadipok
На моем примере помогло, спасибо!

Я у Sleep(100) поставил не для того чтобы ты его к себе скопипастил
Добейся чтоб мой пример работал корректно без слипа. Повторяю проблема в том что передается указатель на i, а в момент чтения по адресу этого указателя в i совсем другое значение.


, работает же
Dima T
Дата: 07.10.2014 15:35:09
vadipok
, работает же

Подумай как работает:
Запускается 1-й поток, пауза 100 мс (за это время он уже завершается), второй, пауза и т.д.
быстрее будет по очереди thread() вызвать 4 раза, последовательно без пауз и лишних потоков
т.е. так
	for(int i = 0; i < 4; i++)
	{
		thread(&i);
	}
vadipok
Дата: 07.10.2014 15:42:06
Dima T
vadipok
, работает же

Подумай как работает:
Запускается 1-й поток, пауза 100 мс (за это время он уже завершается), второй, пауза и т.д.
быстрее будет по очереди thread() вызвать 4 раза, последовательно без пауз и лишних потоков
т.е. так
	for(int i = 0; i < 4; i++)
	{
		thread(&i);
	}


Да я это понял, только пока не знаю как.
Работаю на этим.
mayton
Дата: 07.10.2014 17:53:03
vadipok
, работает же

Это можно распечатать и на стенку повесить.
vadipok
Дата: 07.10.2014 18:47:00
Решил я проблему, возможно не очень красиво. )

		HANDLE hThread;
		HANDLE threads[1000];
		SECURITY_ATTRIBUTES  sa = {sizeof(SECURITY_ATTRIBUTES), 0, TRUE};

		for (d=0;d<(int) ipAddress_vec.size();d++) {
			unsigned threadId;
			
			threads[d] = (HANDLE)_beginthreadex(&sa, 4096, &getDataCPU, (void *) d, 0, &threadId);
			
			//Sleep(100);
		}


unsigned __stdcall getDataCPU( void* pArguments )
{
	cout << (int) pArguments << endl;
	int step = (int) pArguments;
	IPADDRESS ipAddress = ipAddress_vec[step];
	//IPADDRESS *ipAddress2 = static_cast<IPADDRESS*>(pArguments);
	cout << ipAddress.employeeID <<endl;
	cout << ipAddress.ipAddress  <<endl;
	//cout << ipAddress2->step  <<endl;
	cout << GetCurrentThreadId() << endl;
}


Основной смысл в том, что не передаю всю структуру, а только номер шага. Потом вытаскиваю от вектора.

Следующий вопрос остается открытым, как дождаться, чтобы все процессы завершились?
Следующего кода явно не достаточно(Над решением Sleep уже посмеялись ):
		for(d=0;d<ipAddress_vec.size();d++) {
			WaitForSingleObject( threads[d], INFINITE );
			CloseHandle(threads[d]);
		}