Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Функция потока в классе и доступ к его переменным 
V
    Опции темы
EnergoHokum
Дата 6.6.2007, 08:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 600
Регистрация: 10.11.2006
Где: Россия, Ставропол ь

Репутация: 3
Всего: 6



Доброго времени суток всем. Скажите, если есть такой класс
Код

HANDLE threads[5];
DWORD threadsID[5];

class TestThread
{
private:
    int i;
    static DWORD WINAPI thFunc(LPVOID lpParam)
    {
        std::cout<<"TestThread::thFunc() in thread "<<i<<std::endl;
        Sleep(15000);
        return 0;
    }
public:
    TestThread() { i=19; }
    ~TestThread() {;}
    void startThread(void)
    {
        threads[0]=CreateThread(NULL,
                            0,
                            thFunc,
                            0,
                            0,
                            &threadsID[0]);
    }
};

int main(int argc,char** argv)
{
    TestThread tt;
    tt.startThread();
    WaitForSingleObject(threads[0],INFINITE);
    return 0;
}

компилятор ругается, что static-функция не может иметь доступ к переменным класса. Есть ли возможность всё-таки достучаться до них из этой функции?

Добавлено через 6 минут и 45 секунд
Всё, вопрос решён. Передал в thFunc (void*)this, а там получил доступ как ((TestThread*)lpParam)->i;
PM MAIL ICQ   Вверх
Smarts
Дата 8.6.2007, 00:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 67
Регистрация: 23.4.2007

Репутация: 2
Всего: 2



Из статической функции вызывай обычную - в ней и пиши реализацию потока.
PM MAIL   Вверх
zkv
Дата 8.6.2007, 00:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Участник Клуба
Сообщений: 2133
Регистрация: 23.7.2006
Где: Санкт-Петербург

Репутация: 12
Всего: 92



Цитата(Smarts @  8.6.2007,  00:39 Найти цитируемый пост)
Из статической функции вызывай обычную - в ней и пиши реализацию потока. 

а обычную, это какую?
PM MAIL   Вверх
Smarts
Дата 8.6.2007, 01:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 67
Регистрация: 23.4.2007

Репутация: 2
Всего: 2



Обычная - не статическая smile
Только ее нельзя вызвать из статической функции, поэтому надо передать указатель на this и указатель на реализацию потока.

Вот мой класс для подобных целей, может быть кому-нибудь пригодится. Новый класс надо объявить потомком от CThreadingClass и перегрузить виртуальную функцию потока. При длительных вычислениях желательно переодически проверять stopFlag для легкого завершения потока извне.

Код

/* --- ThreadingClass.h --- */

#ifndef _THREADING_CLASS_H_
#define _THREADING_CLASS_H_

class CThreadingClass;
typedef DWORD (WINAPI CThreadingClass::*LPTHREAD_METHOD)(LPVOID lpParam);

typedef struct STARTUP_PARAM
{
    CThreadingClass*    pClass;
    LPTHREAD_METHOD    pMethod;
    LPVOID        pParam;
} *LPSTARTUP_PARAM;


class CThreadingClass
{
// Constructor, destructor
public:
    CThreadingClass();
    virtual    ~CThreadingClass();

// Interface
public:
    DWORD    Start();
    DWORD    Stop();
    DWORD    Resume();
    DWORD    Pause();

// Main thread proc to be defined in child class
protected:
    virtual DWORD WINAPI ThreadProc(LPVOID lpParam) = 0;

// static function that calls ThreadProc
private:
    static DWORD WINAPI ThreadingClass_Thread(LPSTARTUP_PARAM lpParam); 

// Data
protected:
    HANDLE    hThread;
    DWORD    dwThreadID;
    bool    isPaused;
    bool    isRunning;
    bool    stopFlag;

    enum tcErrorCodes
    {
        ERROR_NULL_HTHREAD        = -1,
        ERROR_ALREADY_PAUSED        = -2,
        ERROR_ALREADY_RUNNING        = -3,
        //ERROR_SUCCESS = 0    - defined in windows hearers and means no errors in function
    };

};

#endif // _THREADING_CLASS_H_


Код

/* --- ThreadingClass.cpp --- */

#include "StdAfx.h" // windows.h
#include "ThreadingClass.h"

CThreadingClass::CThreadingClass()
{
    hThread        = NULL;
    dwThreadID    = 0;
    isPaused    = false;
    isRunning    = false;
    stopFlag    = false;
}

CThreadingClass::~CThreadingClass()
{
    Stop();
}


DWORD    CThreadingClass::Start()
{
    LPSTARTUP_PARAM pStartup = new STARTUP_PARAM;

    pStartup->pClass    = this;
    pStartup->pMethod    = &CThreadingClass::ThreadProc;
    pStartup->pParam    = NULL;

    hThread = CreateThread(    NULL, 0, (LPTHREAD_START_ROUTINE)ThreadingClass_Thread, 
                            pStartup, 0, &dwThreadID);
    if(hThread)
    {
        isRunning = true;
        return ERROR_SUCCESS;
    }
    else
        return GetLastError();
}


DWORD    CThreadingClass::Stop()
{
    if(!hThread)    
        return ERROR_NULL_HTHREAD; 

    stopFlag = true;
    WaitForSingleObject(hThread, INFINITE);

    if(CloseHandle(hThread))
    {
        isRunning = false;
        return ERROR_SUCCESS;
    }
    else    
        return GetLastError(); // CloseHandle
}


DWORD    WINAPI CThreadingClass::ThreadingClass_Thread(LPSTARTUP_PARAM lpParam)
{
    CThreadingClass*    pClass    = lpParam->pClass;
    LPTHREAD_METHOD        pMethod    = lpParam->pMethod;
    LPVOID                pParam    = lpParam->pParam;

    delete lpParam; //all info is copied to the first three variables
    return (pClass->*pMethod)(pParam);
}


DWORD    CThreadingClass::Pause()
{
    if(isPaused) 
        return ERROR_ALREADY_PAUSED;

    DWORD dwResult = SuspendThread(hThread);

    if(dwResult != -1)    
    {
        isPaused = true;
        return ERROR_SUCCESS;
    }
    else return GetLastError();
}

DWORD    CThreadingClass::Resume()
{
    if(!hThread) 
        return ERROR_NULL_HTHREAD;
    if(!isPaused) 
        return ERROR_ALREADY_RUNNING;

    DWORD dwResult = ResumeThread(hThread);

    if(dwResult != -1)    
    {
        isPaused = true;
        return ERROR_SUCCESS;
    }
    else return GetLastError();
}


PM MAIL   Вверх
-Kp0T-
Дата 10.6.2007, 15:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 61
Регистрация: 23.2.2007

Репутация: 2
Всего: 2



2 Smarts:
Цитата

...Новый класс надо объявить потомком от CThreadingClass и перегрузить виртуальную функцию потока...

Зачем усложнять жизнь, все можно куда проще разрешить.


2 EnergoHokum:
Подправил немного твой класс:
Код

HANDLE threads[5];
DWORD threadsID[5];
class TestThread
{
private:
    int i;
    static DWORD WINAPI thFunc(LPVOID lpParam)
    {
        std::cout<<"TestThread::thFunc() in thread "<< ((TestThread*)lpParam)-> i<<std::endl;
        Sleep(15000);
        return 0;
    }
public:
    TestThread() {i=19; }
    ~TestThread() {;}
    void startThread(void)
    {
        threads[0]=CreateThread(NULL,
                            0,
                            thFunc(),
                            (LPVOID)this,
                            0,
                            &threadsID[0]);
    }
};
int main(int argc,char** argv)
{
    TestThread tt;
    tt.startThread();
    WaitForSingleObject(threads[0],INFINITE);
    return 0;
}


Здесь дело в том что static-функция не имеет неявного this указателя (то же самое с глобальными friend функциями к классу). Поэтому для доступа надо иметь указатель на экземпляр класса this. 
----
Млин, сорри, не углядел снизу то что ты добавил,
вообщем верно smile

Это сообщение отредактировал(а) -Kp0T- - 10.6.2007, 15:30
PM MAIL   Вверх
Smarts
Дата 10.6.2007, 18:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 67
Регистрация: 23.4.2007

Репутация: 2
Всего: 2



Цитата
Зачем усложнять жизнь, все можно куда проще разрешить.

Люблю когда все структурировано, особенно если требуется написать не такой простой класс без иерархии, как CTestThread smile
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.1051 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.