Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Поток как член класса

319
13 ноября 2003 года
xelos
577 / / 27.02.2003
Такая проблема, внутри класса надо запустить поток с потоковой функцией, являющейся членом класса. В потоковой функции используются переменные объекта и вызываются другие члены класса. Чтобы запустить потоковую функцию, внутри класса ее надо объявлять статической, со всеми вытекающими последствиями - надо объявлять статическими все используемые переменные и функции. Пока у нас один объект класса - все бы хорошо, а когда их много - начинаются проблемы.
Может кто чего посоветует, или я чего не так понимаю в использовании потоков внутри класса?
3
13 ноября 2003 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by xelos
Такая проблема, внутри класса надо запустить поток с потоковой функцией, являющейся членом класса. В потоковой функции используются переменные объекта и вызываются другие члены класса. Чтобы запустить потоковую функцию, внутри класса ее надо объявлять статической, со всеми вытекающими последствиями - надо объявлять статическими все используемые переменные и функции. Пока у нас один объект класса - все бы хорошо, а когда их много - начинаются проблемы.
Может кто чего посоветует, или я чего не так понимаю в использовании потоков внутри класса?



Во-первых, выражение "внутри класса надо запустить поток" неверно по многим причинам.

Во-вторых, в аргументах, передаваемых методу создающему поток (CreateThread или др.), не просто так присутствует "параметр передаваемый в потоковую процедуру" ("The parameter to be passed to the thread procedure"). Вот и передавайте в него указатель на экземпляр класса.

CreateThread(NULL, 0, &ThreadProc, this, 0, &dwThreadID);

4.8K
13 ноября 2003 года
Владислав
19 / / 28.09.2003
Попробуй сделать так:

Код:
// Объявление
class A
{
public:
   A () : m_hThread (NULL), m_A (0), m_B (0) {}
   virtual ~A();
   bool RunThread (void);
   static unsigned int __stdcall Thread (void*);
protected:
   virtual unsigned int CoolThread (void);
   virtual bool MyImpl (void) { return TRUE; }
// Другие методы
protected:
   HANDLE m_hThread;
   int m_A;
   int m_B;
// И т.д.
};

// Определение
unsigned int __stdcall A::Thread (void* p)
{
// Здесь можешь воспользоваться cast'ом
// будет более читабельно.
   return ((A*)p) -> CoolThread ();
}

unsigned int A::CoolThread ()
{
// Работаем с переменными и методами класса,
// например:
   m_A = 2;
   m_B = 1;
   MyImpl ();
// Другие действия  
   return 0;
}

bool A::RunThread ()
{
   unsigned int res = 0;
// Совет: Никогда не пользуй CreateThread, вместо
// этого используй _beginthreadex
   m_hThread = (HANDLE)_beginthreadex (NULL, 0, Thread, this, 0, &res);
   if (!m_hThread)
     assert (0);
}

A::~A()
{
   if (m_hThread)
   {
      // Уничтожение потока
      DWORD res = 0;
      res = ::WaitForSingleObject (m_hThread, 1000);
      switch (res)
      {
         case WAIT_OBJECT_0:
           break;
         case WAIT_TIMEOUT:
           ::TerminateThread (m_hThread, -1);
           break;
         default:
            assert (0);
      }
      ::CloseHandle (m_hThread);
   }
}
319
13 ноября 2003 года
xelos
577 / / 27.02.2003
Цитата:
Originally posted by Green


Во-первых, выражение "внутри класса надо запустить поток" неверно по многим причинам.

Во-вторых, в аргументах, передаваемых методу создающему поток (CreateThread или др.), не просто так присутствует "параметр передаваемый в потоковую процедуру" ("The parameter to be passed to the thread procedure"). Вот и передавайте в него указатель на экземпляр класса.

CreateThread(NULL, 0, &ThreadProc, this, 0, &dwThreadID);


Окей, про "поток внутри класса" согласен, но я же написал, что потоковой функцией должен быть член класса, и поток вызывается из другого члена класса. То бишь все операции с потоком заключены в класс, это я и имел ввиду под "потоком буквоедство прям какое-то, чуть где неточно выразишься, сразу носом тыкают :)
CreateThread вызывается внутри класса (из другой функции- члена класса), в этом и была вся проблема.
Я сделал через вызов через AfxBeginThread
все реализовано следующим образом:
Объявление процедур:

 
Код:
static UINT threading(LPVOID p);

void threading();


вызов потока:
 
Код:
AfxBeginThread(threading, this);


реализация функций:
 
Код:
UINT CMyClass::threading(LPVOID p)
{
    CMyClass * me = (CMyClass *)p;
    me->threading();
    return 0;
}
void CMyClass::threading()
{
    // код
}

решение взято с codeguru
Все работает великолепно, то для чего делалось разделение на потоки выполняется без задоринки.
Однако есть одна вещь, которая меня настораживает - когда я просматриваю потоки в системе (с помощью ProcessExplorer от System Internals), у меня виден только один основной поток моего приложения, второго потока не видно. Что бы это значило?
3
14 ноября 2003 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by xelos

решение взято с codeguru
Все работает великолепно, то для чего делалось разделение на потоки выполняется без задоринки.


Это решение - частный вариант того, о чем я говорил.

Цитата:
Originally posted by xelos

Однако есть одна вещь, которая меня настораживает - когда я просматриваю потоки в системе (с помощью ProcessExplorer от System Internals), у меня виден только один основной поток моего приложения, второго потока не видно. Что бы это значило?


Это возможно в нескольких случиях:
1) поток не был создан, ты проверяешь успешность создания потока?
2) поток уже завешил свое существование ко времени перебора потоков. Как ты задаешь время существования этого потока?

319
14 ноября 2003 года
xelos
577 / / 27.02.2003
Цитата:
Originally posted by Green

Это возможно в нескольких случиях:
1) поток не был создан, ты проверяешь успешность создания потока?
2) поток уже завешил свое существование ко времени перебора потоков. Как ты задаешь время существования этого потока?



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

319
14 ноября 2003 года
xelos
577 / / 27.02.2003
Еще вопрос, при экстренном завершении потока (например, когда он убивается из виндового таск менеджера) можно ли как-нибудь отследить не теряются ли ресурсы? в смысле, можно ли корректно освободить все, что пользуется потоком? А то судя по описанинию, этого сделать невозможно, т.е. если потоком юзается какая-нить dll, например, и поток убивается, хэндлер dll безвозвратно теряется, а сама она из памяти не выгружается.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог