从Visual C ++中的非托管代码更新托管窗体

时间:2011-08-15 18:25:24

标签: c++ visual-studio-2010 backgroundworker

当您单击表单上的按钮时,我有一个运行测试的Windows窗体,EngTest_F()。从本机DLL调用此函数。我还在托管表单代码中创建了一个后台工作程序,它调用函数GetSicStatusMsg来更新表单中的文本框。

在我的原生EngTest_F函数中,我有将文本更新推送到字符串队列的函数。然后,当调用GetSicStatusMsg时,它会检查队列中的字符串并将它们打印到windows窗体中的richTextBox中。

我需要做的是让后台工作人员连续运行GetSicStatusMsg,以便我可以实时了解测试的运行情况。实际发生的是EngTest_F运行,然后在完成后大约一秒钟,所有状态消息立即打印出来。

有没有办法完成我想做的事情?或者有更简单的方法吗?这是我第一次使用线程,文档有点缺乏。

    private: void GetSicStatusMsg()
         {
             try
             {
                 while(GetNumStatusMsgs())
                 {
                     String^ Status = gcnew String(GetStatusMsg().c_str());
                     DisplayStatus(Status, DISPLAY_SIC);
                 }
             }
             catch(SIC_Error *Err)
             {
                 if(Err->ErrorCode != NO_CONTROLLER)
                 {
                     String^ Error = gcnew String(Err->ErrorMsg.c_str());
                     DisplayStatus(Error,DISPLAY_SIC);
                 }
             }
             catch(Exception ^Ex)
             {
                 DisplayStatus(Ex->Message,DISPLAY_SIC);
             }
         }

    private: System::Void button1_Click(System::Object^  /*sender*/, System::EventArgs^  /*e*/) 
         {      
             this->button1->Enabled = false;

             // Enable the Cancel button while 
             // the asynchronous operation runs.
             this->button4->Enabled = true;

             // Start the asynchronous operation. Needs to be running while EngTest_F is running
             backgroundWorker1->RunWorkerAsync();

             EngTest_F();
         }

    private: System::Void backgroundWorker1_ProgressChanged(System::Object^  sender, System::ComponentModel::ProgressChangedEventArgs^  e) 
         {
             GetSicStatusMsg();
         }

    private: void backgroundWorker1_RunWorkerCompleted( Object^ sender, RunWorkerCompletedEventArgs^ e )
         {
             // Enable the Start button.
             button1->Enabled = true;

             // Disable the Cancel button.
             button4->Enabled = false;
         }

    private: void backgroundWorker1_DoWork( Object^ sender, DoWorkEventArgs^ e )
         {
             // Get the BackgroundWorker that raised this event.
             BackgroundWorker^ worker = dynamic_cast<BackgroundWorker^>(sender);

             worker->ReportProgress(0);
         }

1 个答案:

答案 0 :(得分:0)

您的代码似乎是倒退的。 UI线程应该更新UI,后台线程应该执行长时间运行的任务(我猜这是EngTest_F())。解决此问题的一种方法是使用System.Windows.Forms.Timer组件。设置Interval = 50左右的计时器,调用GetSicStatusMsg()来更新UI。任务启动时启用计时器,并在任务完成时将其禁用。

我不是BackgroundWorker的专家(我倾向于自己使用普通的Thread对象),但我打赌你需要在任务进行时调用ReportProgress;您的代码只调用一次ReportProgress。我建议在你的情况下使用普通的Thread + a Timer,因为你的非托管代码可能很难调用BackgroundWorker.ReportProgress()。