2014-01-13 61 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

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