2014-01-13 60 views
0

我有一个类动态实例化(因为指针是通过C接口来回传递的),它具有成员加速线程。在一个成员函数下面的代码被执行:Boost线程内部线程无法访问成员变量

_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

哇,请减少文本长度或以更好的方式进行格式化,但IMO不太可能会有人阅读这段文字。 – Paranaix

回答

0

这是很难告诉你的问题实际上是在这里,并没有足够的代码可以肯定的,但这种判断:

的问题是它里面的队列[传递到通过指针线程函数]似乎没有初始化

一个可能的原因(再次,我猜,我没有什么可去的),就是this指针你传递给线程实际上是一个指针t o一个本地实例化的自动变量,随后在线程启动之前被销毁。

例如:

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

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

会复制我所描述的行为。请注意,你真正看到的是未定义的行为,所以任何事情都可能发生。

+0

谢谢你试图破译我的问题!这种可能性是有道理的,但我不明白这一点。有没有与复制构造函数或赋值运算符有关的东西?两者都是涉及到的一切的默认设置。 – Grasshopper

+0

有可能;我需要看到更多的代码。 –