【问题标题】:Windows Form Show vs ShowDialogWindows 窗体显示与 ShowDialog
【发布时间】:2013-08-31 17:58:29
【问题描述】:

我有一个正在尝试为 Windows 创建的小型应用程序。我遇到了混合用于处理某些数据的后台线程的问题。这个后台引擎需要更新应用程序 gui(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

我真的不能把这两个东西混在一起,起初我只想把引擎扔到 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);
        }
    };

【问题讨论】:

  • 如果有人想知道,我使用 Gui 类中的后台工作人员解决了这个问题。
  • 如果您自己找到解决方案,最好创建您的答案并接受它...
  • 谢谢法比奥。我就是这么做的。

标签: c++ windows winforms modal-dialog


【解决方案1】:

据我所知,这是让后台线程更新 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);
    }
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    • 2018-06-06
    • 2010-09-28
    • 1970-01-01
    • 2010-11-22
    • 1970-01-01
    相关资源
    最近更新 更多