Обновление управляемой формы из неуправляемого кода в Visual C ++ - PullRequest
0 голосов
/ 15 августа 2011

У меня есть форма Windows, которая запускает тест EngTest_F (), когда вы нажимаете кнопку в форме. Эта функция вызывается из собственной библиотеки DLL. Я также создал фонового работника в коде управляемой формы, который вызывает функцию GetSicStatusMsg для обновления текстового поля в форме.

В моей родной функции EngTest_F у меня есть функции, которые помещают текстовые обновления в очередь строк. Затем, когда вызывается GetSicStatusMsg, он проверяет очередь на наличие строк и печатает их в 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 голосов
/ 16 августа 2011

Кажется, ваш код задом наперед. Поток пользовательского интерфейса должен обновить пользовательский интерфейс, а фоновый поток должен выполнить долгосрочную задачу (я полагаю, это EngTest_F ()). Один из способов добиться этого - использовать компонент System.Windows.Forms.Timer. Установите таймер с интервалом = 50 или около того, который вызывает GetSicStatusMsg () для обновления пользовательского интерфейса. Включите таймер при запуске задания и отключите его по завершении задания.

Я не большой эксперт в BackgroundWorker (я обычно использую обычные объекты Thread), но держу пари, что вам нужно вызывать ReportProgress всякий раз, когда задача выполняется; Ваш код вызывает ReportProgress только один раз. Я рекомендую использовать простой поток + таймер в вашем случае, потому что вашему неуправляемому коду, вероятно, трудно вызвать BackgroundWorker.ReportProgress ().

...