【发布时间】:2016-10-17 18:12:40
【问题描述】:
我有一个 MainForm 类(如您所料,它是一个表单),上面有一个文本框。我还有另一个名为“Application_Server”的类,它可以做很多其他的事情(不仅仅是与表单背景相关,还有很多基于网络的东西等)。
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不同的线程上创建的,这似乎不正确。 -
这段代码不会死锁吗?对
Invoke()的调用将导致在UI 线程上调用postDebugMessage(),这将导致它等待由调用线程持有的DebugTextBox... -
是的,它确实陷入了僵局,出于兴趣,你会如何巧妙地做到这一点,以免它不会?我下面的示例(将 Invoke 调用推送到另一个调用该方法的对象)看起来很乱,例如,如果我忘记调用怎么办?
标签: multithreading c++-cli command-line-interface invoke