0

У меня есть экземпляр класса, динамически созданный (поскольку указатель передается обратно и вперед через интерфейс C), который имеет поток повышения элемента. В функции члена следующий код выполняется:Boost Thread внутри класса не может получить доступ к переменным-членам

_thrd = boost::thread(boost::bind(&cls::thrdProc, this, other vars)); 

Я знаю следующее: Нить была создана Поскольку процедура нить не является статической функции члена того же класса «это» передается как первый аргумент. Я пробовал это с и без boost :: bind.

Также в этом классе является переменной-членом очереди, которую я написал. Процедура потока создает скрытое окно сообщения, инициализируется библиотека связи, и по мере поступления данных библиотека отправляет сообщение Windows в процедуру сообщения (которая находится в потоке). Процедура сообщения отправляет сообщение в процедуру статического окна, которая перенаправляет ее на функцию-член того же класса с потоком. Получены сообщения и вводится процедура потока. Проблема заключается в том, что очередь не инициализируется (фактически все переменные-члены класса недопустимы). Таким образом, поскольку процедура потока и основной код приложения используют boost :: mutex для защиты данных очереди через какое-то время (зависит от количества пакетов, полученных библиотекой связи), я получаю ошибку времени выполнения на boost::lock_guard (также попытался boost::scoped_lock). Это потому, что процедура потока вызывает _queue.push, которая пытается заблокировать мьютекс, который не инициализирован, так что BOOST_VERIFY жалуется.

Я прочитал несколько вопросов и примеров, в которых упоминаются аргументы потоков, но аргументы не являются проблемой. Кажется, this указывает на что-то еще или объект класса-оболочки не существует. Это действительно так, и я могу подтвердить, что исходный указатель действителен.

Есть ли другая проблема с копией, о которой я не знаю? Спасибо заранее!

 HEADER FILE 

interface language_proxy 
{ 
virtual int connectToQ(int * id) = 0; 
virtual int deconnectFromQ(int const id) = 0; 
virtual int startDataCollection() = 0; 
virtual int stopDataCollection() = 0; 
... 
}; 

class CMyThread : public language_proxy 
{ 
public: 
    CMyThread(com lib args); 

    int connectToQ(int * id); 
    int deconnectFromQ(int const id); 
    int startDataCollection(); 
    int stopDataCollection(); 
    ... 

protected: 
    boost::mutex  _mutex; 
    CMyQueue   _queue; 
    boost::thread  _thrd; 
    ... 

    uint thrdProc(com lib args); 
}; 


EXECUTABLE FILE(S) 

int CMyThread::startDataCollection() 
{ 
// guard against multiple starts 
if(boost::thread:id() == _thrd.get_id()) 
    { 
    _thrd = boost::thread(boost::bind(&CMyThread::thrdProc, this, member vars for com lib)); 
    } 
} 

uint CMyThread::thrdProc(com lib args) 
{ 
// create hidden messaging window 
WNDCLASSEX     wc     = { 0 }; 

// many parameters can be ignored since window will be hidden 
wc.cbSize  = sizeof(WNDCLASSEX); 
wc.lpszClassName = MSG_WND_CLS; 
wc.lpfnWndProc = &CMyThread::StaticWndProc; 
wc.hInstance  = GetModuleHandle(0); 

// register the class with Windows 
RegisterClassEx(&wc); 

// create a window based on the above class parameters 
_msg_hwnd = CreateWindowEx 
       (
       0, 
       wc.lpszClassName, 
       L"HiddenMessageWindow", 
       0, 
       CW_USEDEFAULT, 
       CW_USEDEFAULT, 
       0, 
       0, 
       HWND_MESSAGE, 
       0, 
       0, 
       this 
       ); 

// initialize com lib 

// process windows messages 
while(true) 
    { 
    // process available messages 
    if(PeekMessage(&msg, _msg_hwnd, 0, 0, PM_REMOVE)) 
     { 
     // break out of the loop if the quit message is found 
     if(WM_QUIT == msg.message) 
      { 
      printf("Quit message found\n"); 
      break; 
      } 

     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
     } 

    else 
     { 
     // throws boost::thread_interrupted if the thread has been interrupted 
     boost::this_thread::sleep_for(boost::chrono::milliseconds(_msg_loop_dly)); 
     } 
    } 

UnregisterClass(MSG_WND_CLS, GetModuleHandle(0)); 
} 

LRESULT CALLBACK CMyThread::StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
CMyThread *   pWnd    = 0; 

try 
{ 
// store class pointer for window being created 
if(WM_NCCREATE == uMsg) 
    { 
    // use SetWindowLongPtr to be 64-bit compatible (a class pointer will be 64 bits and a long is only 32 bits) 
    pWnd = (CMyThread *)((LPCREATESTRUCT)lParam)->lpCreateParams; 
    SetWindowLongPtr(hWnd, GWLP_USERDATA, *reinterpret_cast< LONG_PTR * >(pWnd)); 
    } 

// access the class pointer 
else 
    { 
    pWnd = (CMyThread *)GetWindowLong(hWnd, GWL_USERDATA); 
    } 

// if a class pointer for the window exists, call its procedure 
if(pWnd) 
    { 
    return(pWnd->WndProc(hWnd, uMsg, wParam, lParam)); 
    } 
} 

catch(...) 
{ 
int x = 5; 
} 

// call the default window procedure 
return(DefWindowProc(hWnd, uMsg, wParam, lParam)); 
} 

LRESULT CALLBACK CMyThread::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
switch(uMsg) 
    { 
    // when a request to close the window is received, destroy the window 
    case WM_CLOSE: 
     { 
     DestroyWindow(hWnd); 
     } break; 

    // when a window is destroyed put a quit message in the queue to stop message processing 
    case WM_DESTROY: 
     { 
     PostQuitMessage(0); 
     } break; 

    // handle messages from com library 
    case UWM_RX_COM_LIB_MSG: 
     { 
     // use GetWindowLongPtr to be 64-bit compatible (a class pointer will be 64 bits and a long is only 32 bits) 
     LONG_PTR   lPtr    = GetWindowLongPtr(hWnd, GWLP_USERDATA); 
     CMyThread *   pWnd    = reinterpret_cast< CMyThread * >(&lPtr); 
     pWnd->onRx(); 
     } break; 

    // handle all other cases by default behaviour 
    default: 
     { 
     return(DefWindowProc(hWnd, uMsg, wParam, lParam)); 
     } 
    } 

return(0); 
} 

void CMyThread::onRx() 
{ 
// extract packet(s) from com library 
// add packet(s) to vector 

// THIS QUEUE IS UNINITIALIZED! 
_queue.push(pkts); 
} 

int C_Interface_create 
    (
    com lib arguments, 
    language_proxy ** p 
    ) 
{ 
// instantiate the C++ object through the C interface 
language_proxy *  tmp_p  = new CMyThread(com lib args); 

if(tmp_p) 
    { 
    *p = tmp_p; 
    } 

    return(0); 
} 

int C_Interface_start_thread(language_proxy * p) 
{ 
p->startDataCollection(); 
    return(0); 
} 


// actually in a DLL but so you have some idea of what the operation flow is 
void main() 
{ 
static language_proxy *  s_proxy = 0; 

C_Interface_create(1, 2, 3, &s_proxy); 
c_Interface_start_thread(s_proxy); 

// for debugging, endless loop to allow rx'd packets to be processed and guarantee 
// s_proxy is still alive 
while(1); 
} 
+0

wow, пожалуйста, уменьшите длину текста или лучше отформатируйте его, но IMO очень маловероятно, чтобы кто-нибудь прочитал эту стену текста. – Paranaix

ответ

0

Это было трудно сказать, что на самом деле был здесь свой вопрос, и не хватает кода, чтобы быть уверенным, но судя из этого:

Проблема находится внутри него очередь [передается функция резьбы по указателю], как представляется, не были инициализированы

Одна из возможных причин этого (опять же, я предполагаю, что я не имею ничего, чтобы пойти на), является то, что this указатель вы передаете к thread на самом деле является указателем t o автоматическая переменная, созданная локально, которая впоследствии уничтожается до запуска вашего потока.

Например:

void MyQueue::startTheThread() 
{ 
    _thrd = boost::thread(boost::bind(&cls::thrdProc, this, other vars)); 
} 

int someFreeFunction() 
{ 
    MyQueue q; 
    q.startTheThread(); 
} 

бы повторить поведение я описываю. Обратите внимание, что то, что вы на самом деле видите, - это неопределенное поведение, поэтому все может случиться.

+0

Спасибо, что пытались расшифровать мою проблему! Эта возможность имеет смысл, но я не совсем понимаю это. Может ли быть что-то, связанное с конструктором копирования или оператором присваивания? Оба являются значениями по умолчанию для всех задействованных. – Grasshopper

+0

Может быть; Мне нужно будет увидеть больше кода. –