2016-10-17 76 views
1

我有一個MainForm類(如你所期望的那樣,它是一個表單)上有一個文本框。我還有另一個名爲'Application_Server'的類,它負責其他的東西(不僅僅是與表單背景有關的東西,還有很多基於網絡的東西等等)。C++ CLI調用問題

Application_Server類運行在它自己的線程中,但需要能夠更新窗體上的控件,對於這個問題,我們將只使用文本框。

的問題是,即使我在執行命令來設置通過「調用」 TextBox控件的文本,我仍然獲得在運行時出現以下異常:

其他信息:跨線程操作無效:控制 'DebugTextBox'從一個線程訪問,而不是線程創建的線程爲 。

什麼可能導致這種情況?我絕對在MainForm中調用一個委託。

下面是相關的代碼段(上剪下來的可讀性):

MainForm.h:

public ref class MainForm : public System::Windows::Forms::Form { 

     delegate void del_updateDebugText(String^ msg); 
     del_updateDebugText^ updateDebugText = gcnew del_updateDebugText(this, &MainForm::postDebugMessage); 

private: void postDebugMessage(String^ message); 
}; 

MainForm.cpp:

void EagleEye_Server::MainForm::postDebugMessage(String^ message) 
{ 
    Monitor::Enter(DebugTextBox); 
    if (this->DebugTextBox->InvokeRequired) 
    { 
     this->Invoke(updateDebugText, gcnew array<Object^> { message }); 
    } 
    else 
    { 
     this->DebugTextBox->AppendText(message); 
    } 
    Monitor::Exit(DebugTextBox); 
} 

最後,代碼調用它:

void ServerAppManager::postDebugMessage(System::String^ message) 
{ 
    mainFormHandle->updateDebugText(message); 
} 

void ServerAppManager::applicationStep() 
{ 
    postDebugMessage("Starting\n"); 
    // This is Run in seperate thread in MainForm.cpp 
    while (s_appState == ApplicationState::RUN) 
    {  
     postDebugMessage("Testing\n");  
    } 

} 

謝謝!

+0

一切看起來都很好,但是你正在用'MainForm'而不是'TextBox'調用'Invoke()'。你可以嘗試用'TextBox'調用'Invoke()'來查看是否有幫助。如果解決了這個問題,就意味着'TextBox'可能已經在與MainForm不同的線程上創建,這看起來不正確。 – Andy

+0

這段代碼不會死鎖嗎?對'Invoke()'的調用會導致'postDebugMessage()'在UI線程上被調用,這會導致它等待調用線程所持有的'DebugTextBox' ... – Medinoc

+0

是的,它確實死鎖,出於興趣,你會如何整齊地做到這一點?我在下面的例子(將Invoke調用推送到另一個調用方法的對象)看起來很混亂,例如,如果我忘記調用? –

回答

-1

我設法得到它的工作由「MainForm的」類中的簡化方法:

void EagleEye_Server::MainForm::postDebugMessage(String^ message) 
{ 
    Monitor::Enter(DebugTextBox); 
    DebugTextBox->AppendText(message); 
    Monitor::Exit(DebugTextBox); 
} 

然後「調用」調用移動到方法調用的委託,不漂亮,但它適用於現在。我認爲這個問題可能是由於表單陷入Invoke循環中造成的。我說這是因爲我注意到窗體會在鎖定遞歸調用語句後鎖定並停止響應。

+0

我沒有把這個標記爲答案,因爲我相信這是解決這個問題的更好方法,並且希望在有人發佈解決方案時將其作爲答案進行投票。 –