Multithreading C++;CLI调用问题
我有一个MainForm类(正如您所期望的,它是一个表单),上面有一个文本框。我还有另一个名为“Application_Server”的类,它可以做很多其他的事情(不仅仅是与后台相关的表单,还有很多基于网络的东西等等) Application_Server类在它自己的线程中运行,但需要能够更新表单上的控件,对于这个问题,我们将只使用文本框 问题是,即使我正在执行命令,通过“Invoke”设置textBox控件的文本,但在运行时仍会出现以下异常: 其他信息:跨线程操作无效:控件 “DebugTextBox”是从其所在线程以外的线程访问的 创建于 这可能是什么原因造成的?我肯定是在调用MainForm中的委托 以下是相关的代码段(为了可读性而缩减): 主要表格h:Multithreading C++;CLI调用问题,multithreading,c++-cli,command-line-interface,invoke,Multithreading,C++ Cli,Command Line Interface,Invoke,我有一个MainForm类(正如您所期望的,它是一个表单),上面有一个文本框。我还有另一个名为“Application_Server”的类,它可以做很多其他的事情(不仅仅是与后台相关的表单,还有很多基于网络的东西等等) Application_Server类在它自己的线程中运行,但需要能够更新表单上的控件,对于这个问题,我们将只使用文本框 问题是,即使我正在执行命令,通过“Invoke”设置textBox控件的文本,但在运行时仍会出现以下异常: 其他信息:跨线程操作无效:控件 “DebugTex
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);
}
谢谢 我将“MainForm”类中的方法简化为:
void EagleEye_Server::MainForm::postDebugMessage(String^ message)
{
Monitor::Enter(DebugTextBox);
DebugTextBox->AppendText(message);
Monitor::Exit(DebugTextBox);
}
然后将“Invoke”调用移动到调用委托的方法,虽然不太漂亮,但它现在可以工作。我认为问题可能是由于表单卡在调用循环中造成的。我这样说是因为我注意到表单在命中递归调用语句后会锁定并停止响应。从名为bwSearch的后台工作程序中,我们从DoWork事件处理程序执行以下调用:
private: System::Void bwSearch_DoWork(System::Object^ sender, System::ComponentModel::DoWorkEventArgs^ e) {
//... logic
UpdateTxtOutput("Some message");
//... more logic
}
我有一个名为txtOutput的RitchTextBox,还有一个包含此代码的windows窗体控件名为frmMain,UpdateTextOutput由以下三部分定义:
delegate void UpdateTxtOutputDelegate(String^ text);
void UpdateTxtOutput(String^ text)
{
UpdateTxtOutputDelegate^ action = gcnew UpdateTxtOutputDelegate(this, &frmMain::Worker);
this->BeginInvoke(action, text);
}
void Worker(String^ text)
{
txtOutput->AppendText("\t" + text + "\n");
}
一切似乎都很好,但您正在使用
MainForm
而不是文本框调用Invoke()
。您可以尝试使用文本框调用Invoke()
,看看这是否有帮助。如果这解决了问题,则意味着TextBox
可能是在与MainForm
不同的线程上创建的,这似乎不正确。这段代码不会死锁吗?调用Invoke()
将导致在UI线程上调用postDebugMessage()
,这将导致它等待调用线程持有的DebugTextBox
。是的,它确实发生了死锁,出于兴趣,您将如何巧妙地执行它以避免死锁?下面我的示例(将调用推送到调用该方法的另一个对象)看起来很混乱,例如,如果我忘记调用怎么办?我没有将此标记为答案,因为我确信这是解决此问题的更好方法,如果有人发布解决方案,我想将其作为答案投票。
delegate void UpdateTxtOutputDelegate(String^ text);
void UpdateTxtOutput(String^ text)
{
UpdateTxtOutputDelegate^ action = gcnew UpdateTxtOutputDelegate(this, &frmMain::Worker);
this->BeginInvoke(action, text);
}
void Worker(String^ text)
{
txtOutput->AppendText("\t" + text + "\n");
}