我有一個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");
}
}
謝謝!
一切看起來都很好,但是你正在用'MainForm'而不是'TextBox'調用'Invoke()'。你可以嘗試用'TextBox'調用'Invoke()'來查看是否有幫助。如果解決了這個問題,就意味着'TextBox'可能已經在與MainForm不同的線程上創建,這看起來不正確。 – Andy
這段代碼不會死鎖嗎?對'Invoke()'的調用會導致'postDebugMessage()'在UI線程上被調用,這會導致它等待調用線程所持有的'DebugTextBox' ... – Medinoc
是的,它確實死鎖,出於興趣,你會如何整齊地做到這一點?我在下面的例子(將Invoke調用推送到另一個調用方法的對象)看起來很混亂,例如,如果我忘記調用? –