我正在尝试为Windows创建一个小应用程序。我遇到了混合用于处理某些数据的后台线程的问题。这个后台引擎有人需要更新应用程序gui(窗口窗体)并从中获取信息。
这是基本的应用程序主体。
int main() {
Engine engine;
Gui g;
engine.run(); // creates a new thread for engine logic
g.ShowDialog();
bool running = false;
while(1)
{
// Update gui with information from the engine
g.update(engine.GetState());
// transition to running
if(g.isRunning() && !running)
{
engine.play();
running = true;
}
// transition to stopped
else if(!g.isRunning() && running)
{
engine.stop();
running = false;
}
}
}
我的主要问题来自Gui课程的管理。见下面的类声明。
public ref class Gui : public System::Windows::Forms::Form
我真的无法混合这两件事,起初我只是想把引擎扔进Gui但是因为它没有管理而不起作用。
你会注意到这里的问题是调用ShowDialog(),因为这会使对话框模态化并且之后没有代码被执行。但是,如果我使用Show()...... Gui根本不会更新或处理任何输入。
解决方案:
我在Gui类中创建了一个后台工作器,因此引擎包含在Gui中,但是在另一个线程上运行。
void InitializeBackgoundWorker()
{
this->backgroundWorker1 = gcnew System::ComponentModel::BackgroundWorker;
backgroundWorker1->DoWork += gcnew DoWorkEventHandler( this, &Gui::backgroundWorker1_DoWork );
backgroundWorker1->RunWorkerAsync( );
}
delegate void UpdateCallback(int hp, int maxhp);
void UpdateGui(int hp, int maxhp)
{
this->playerHealthBar->Value = ((float)(hp)/(float)(maxhp) * 100.0f);
};
void backgroundWorker1_DoWork( Object^ sender, DoWorkEventArgs^ e )
{
aBotEngine engine;
while(true)
{
engine.runnable(NULL);
array<Object^>^args = gcnew array<Object^>(2);
args[0] = engine.getPlayerHp();
args[1] = engine.getPlayerMaxHp();
this->playerHealthBar->Invoke(gcnew UpdateCallback(this, &Gui::UpdateGui), args);
}
};
答案 0 :(得分:0)
据我所知,这是使用后台线程更新Windows窗体的正确方法。我确定这不是唯一的方法。
void InitializeBackgoundWorker()
{
this->backgroundWorker1 = gcnew System::ComponentModel::BackgroundWorker;
backgroundWorker1->DoWork += gcnew DoWorkEventHandler( this, &Gui::backgroundWorker1_DoWork );
backgroundWorker1->RunWorkerAsync( );
}
delegate void UpdateCallback(int hp, int maxhp);
void UpdateGui(int hp, int maxhp)
{
this->playerHealthBar->Value = ((float)(hp)/(float)(maxhp) * 100.0f);
};
void backgroundWorker1_DoWork( Object^ sender, DoWorkEventArgs^ e )
{
aBotEngine engine;
while(true)
{
engine.runnable(NULL);
array<Object^>^args = gcnew array<Object^>(2);
args[0] = engine.getPlayerHp();
args[1] = engine.getPlayerMaxHp();
this->playerHealthBar->Invoke(gcnew UpdateCallback(this, &Gui::UpdateGui), args);
}
};