Страница 1 из 2

(?) Класс + Многопоточность

Добавлено: 14 фев 2005, 11:22
Lev
Привет всем.

У меня проблема, о ней ниже.
Цель:
Необходимо создать класс, который при своей инициализации (с помощью
коструктора) создавал бы поток, который в свою очередь мог бы иметь доступ к
члена класса, в котором он создан.

Код(упрощенный) такой:

class Ms
{

public:
Ms();
HANDLE heExit;
unsigned int WINAPI Rt(PVOID pvParam);

private:
HANDLE htRt;

};

Ms::Ms()
{
unsigned threadID;
heExit = CreateEvent(NULL, TRUE, FALSE, NULL);

htRt = (HANDLE)_beginthreadex( NULL, 0, &Rt, NULL, 0, &threadID ); // (?)
}

Проблема:
Компилятор ругается error C2276: '&' : illegal operation on bound member
function expression.

но если поставить в определении класса вместо unsigned int WINAPI Rt(PVOID
pvParam); поставить static unsigned int WINAPI Rt(PVOID pvParam); то
_beginthreadex спокойно это переваривает. Но мне не нужна статическая
функция - она не может получить доступ к нестатическим членам класса.

Спасибо.

Добавлено: 14 фев 2005, 12:11
Absurd
Надо просунуть указатель this через параметр callback - функции.

htRt = (HANDLE)_beginthreadex( NULL, 0, &threadFunc, this, 0, &threadID );

//.....

static unsigned int __stdcall threadFunc(void* pvParam) {
Ms *this__ = static_cast<Ms *>(pvParam);
return this__->Rt();
}

Добавлено: 14 фев 2005, 13:49
Lev
Непомогает, пишет всё тоже:
error C2276: '&' : illegal operation on bound member function expression

Добавлено: 14 фев 2005, 14:08
Absurd
Непомогает, пишет всё тоже:
А ты threadFunc статической сделал?

Добавлено: 14 фев 2005, 14:13
Romeo
Наверное ты забыл вместо Rt в вызове _beginthreadex, написать threadFunc. Других причин столь странного поведения не вижу.

Добавлено: 14 фев 2005, 14:16
WinMain
Посмотри, как я делал:

Код: Выделить всё

#include "MyDlgClass.h"

// Эта функция выполняется в отдельном потоке...
unsigned __stdcall DlgConfigFunc(void *v)
{
	if (!v) return 0;

	((CMyDlgClass*)v)->UpdateDlgConfig();
	return 1;
}

// Обработчик какого-то события в окне диалога...
LRESULT CMyDlgClass::OnDlgEventResponse(<список аргументов>)
{
	_beginthreadex(NULL, 0, DlgConfigFunc, this, 0, NULL);
	return 0;
}

void CMyDlgClass::UpdateDlgConfig()
{
	// Какой-то код...
}


Добавлено: 14 фев 2005, 14:46
Absurd
Вообще-то говоря желательно пользоваться имеющимися тредами вместо порождения новых:

unsigned __stdcall DlgConfigFunc(void *v)
{
do {
if(WaitForSingleObject(hEvent, INFINITE) != WAIT_OBJECT_0 || endFlag) { break; }
((CMyDlgClass*)v)->UpdateDlgConfig();
} while (1);
return 0;
}

LRESULT CMyDlgClass::OnDlgEventResponse(<список аргументов>)
{
SetEvent(hEvent);
return 0;
}

Добавлено: 14 фев 2005, 17:38
Lev
#include "MyDlgClass.h"

// Эта функция выполняется в отдельном потоке...
unsigned __stdcall DlgConfigFunc(void *v)
{
if (!v) return 0;

((CMyDlgClass*)v)->UpdateDlgConfig();
return 1;
}

// Обработчик какого-то события в окне диалога...
LRESULT CMyDlgClass::OnDlgEventResponse(<список аргументов>)
{
_beginthreadex(NULL, 0, DlgConfigFunc, this, 0, NULL);
return 0;
}

void CMyDlgClass::UpdateDlgConfig()
{
// Какой-то код...
}
Спасибо. Этот прием мне помог. С помощью него можно решить задачу мою.
Но хотелось бы всетаки запускать функцию-член класса что бы было поменьше глобальных функций.

Добавлено: 14 фев 2005, 17:41
Eugie
Но хотелось бы всетаки запускать функцию-член класса что бы было поменьше глобальных функций.
Нестатический метод класса НЕ МОЖЕТ быть функцией потока: у них разные сигнатуры, и что хуже, соглашения по вызову.

Добавлено: 14 фев 2005, 17:46
Lev
Спасибо всем, помогли. Вопросов больше пока не имею.