开发者

Updating a Managed Form from unmanaged code in Visual C++

开发者 https://www.devze.com 2023-03-28 10:36 出处:网络
I have a Windows Form that runs a test, EngTest_F(), when you click a button on the form. This function is called from a native DLL. I\'ve also created a backgroundworker in the managed form code that

I have a Windows Form that runs a test, EngTest_F(), when you click a button on the form. This function is called from a native DLL. I've also created a backgroundworker in the managed form code that calls a function GetSicStatusMsg to update a textbox in the form.

In my native EngTest_F function, I have functions that push text updates onto a queue of strings. Then when GetSicStatusMsg is called, it checks the queue for strings and prints them out into the richTextBox in the windows form.

What I need to happen is for the backgroundworker to continuously run GetSicStatusMsg so I can get real-time progress on how the test is running. What's actually happening is that EngTest_F runs, and then about a second after it finishes, all the status messages are printed out at once.

Is there a way to accomplish what I want to do? Or is there an easier approach? This is my first time using threads and the documentation is a bit lacking.

    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);
         }


It seems like your code is backwards. The UI thread should update the UI, and the background thread should do the long-running task (I guess that's EngTest_F()). One way to approach this is with a System.Windows.Forms.Timer component. Set up a timer with Interval=50 or so, which calls GetSicStatusMsg() to update the UI. Enable the timer when the task starts, and disable it when the task is complete.

I'm not much of an expert in BackgroundWorker (I tend to use ordinary Thread objects myself), but I bet you need to call ReportProgress whenever the task progresses; your code only calls ReportProgress once. I recommend using a plain Thread + a Timer in your case, because it's probably difficult for your unmanaged code to call BackgroundWorker.ReportProgress().

0

精彩评论

暂无评论...
验证码 换一张
取 消