Windows用に作成しようとしている小さなアプリケーションがあります。一部のデータを処理するように設計されたバックグラウンド スレッドが混在しているという問題が発生しています。このバックグラウンド エンジンは、アプリケーション GUI (A Windows フォーム) を更新し、そこから情報を取得する必要があります。
これが基本的なアプリケーションのメインです。
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
これら 2 つのことを実際に混在させることはできません。最初はエンジンを 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);
}
};