C++ 调试Invoke()调用会导致调试器停止工作
我有一个WinForm的方法,该方法由创建WinForm的线程以外的线程调用。调试时,我到达一行调用C++ 调试Invoke()调用会导致调试器停止工作,c++,multithreading,winforms,visual-studio-2017,invoke,C++,Multithreading,Winforms,Visual Studio 2017,Invoke,我有一个WinForm的方法,该方法由创建WinForm的线程以外的线程调用。调试时,我到达一行调用this->Invoke()和调试器似乎跳过该行并继续正常执行。但是,正常执行会有程序循环,并不断地到达Invoke调用,但不会返回到它 我在Visual Studio 2013和2017中经历过这种情况 //GUI.h delegate void Whatever(System::String ^ text); void SetConsoleTextBoxText(System::String
this->Invoke()代码>和调试器似乎跳过该行并继续正常执行。但是,正常执行会有程序循环,并不断地到达Invoke
调用,但不会返回到它
我在Visual Studio 2013和2017中经历过这种情况
//GUI.h
delegate void Whatever(System::String ^ text);
void SetConsoleTextBoxText(System::String^ input)
{
if (this->consoleTextBox->InvokeRequired)
{
Whatever^ we = gcnew Whatever(this, &GUI::SetConsoleTextBoxText);
this->Invoke(we, gcnew array<Object^> { input }); //debugger hits this and breaks
}
else
{
this->consoleTextBox->Text = input;
this->consoleTextBox->Refresh();
}
}
ref struct Globals {
static GUI ^ gui; //this is my "Global WinForm"
};
一段时间以来,我一直在努力解决更新ConsoleTextBox
时出现的问题,并且在调试该问题时遇到了困难
我的语法错了吗
我的调试是否设置为忽略第一个错误
为什么调试器会执行/跳过一行,然后继续运行程序而不会再次遇到错误
提前感谢。我仍然不知道为什么调试器在调用调用时“中断”
但是,我已经修复了导致调用
出现问题的线程问题,因此我不再面临这个问题
我在我的GUI.h
文件中创建了线程,单击开始按钮
,而不是稍后在程序中,在GUI.cpp
文件中创建线程
为了更加具体,我的按钮
方法(在GUI.h
中)调用在GUI.h
中声明并在GUI.cpp
中定义的方法。我最初是在GUI.cpp函数中创建线程的。现在,我在按钮中创建线程,单击GUI.h
中的方法,让该线程调用GUI.cpp
中的方法。GUI.cpp
中的方法将方法调用到SetTextBoxText
。如果所属线程以外的线程正在调用该方法,则该方法现在可以调用本身(在我的例子中,总是这样)
这是我的解决办法。如果有人能解释为什么这会使线程更安全,我很想知道。是否有可能控件(或窗体)的窗口句柄尚未创建?选中IsHandleCreated,因为如果不是,则不应尝试设置文本,因为这可能会导致在错误的线程上创建句柄。嘿@Ben,文本框肯定已经创建,但只是为了检查,我包含了语句if(this->consoleTextBox->IsHandleCreated)
并且它确实返回true
。我建议您将工作转移到一个单独的函数SetConsoleTextBoxTextImpl
,即Whatever^we=gcnewwhatever(this,&GUI::SetConsoleTextBoxTextImpl)代码>这样您就不会执行两次检查了,这就是重点。我可以从任何线程调用SetConsoleTextBoxText
,它将检查是否需要通过最初创建控件的线程调用Invoke
。对自身的调用只会使它可以从任何线程调用。然而,为了确保这不是问题所在,我继续尝试了一下。当调试器到达Invoke()
行时,也会发生同样的情况,调试器似乎会进入该行,然后忽略/继续,并且永远不会再次到达该语句,尽管它确实应该这样做。对被调用方法的实际调用将在GUI线程上,而不是当前线程上,因此不会进入该线程。尝试在GUI更新的区域内设置一个断点,您应该能够捕获其他线程的处理。
//Different .cpp file
//Running on a different thread than the WinForm "GUI" was made on
MethodThatIsCalledALotInALoop()
{
System::String^ sysStr = "some string";
GUI_Example_Receive::Globals::gui->SetConsoleTextBoxText(sysStr);
}