2011-08-15 109 views
0

當窗體上單擊一個按鈕時,我有一個運行測試的Windows窗體EngTest_F()。這個函數是從本地DLL中調用的。我還在託管表單代碼中創建了一個後臺工作,該代碼調用函數GetSicStatusMsg來更新表單中的文本框。從Visual C++中的非託管代碼更新託管窗體

在我的本地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); 
     } 
+0

您可能經常調用ReportProgress(),導致UI線程充斥着調用請求,因此它不再適應其正常職責。通過添加System :: Threading :: Thread :: Sleep(50)來檢查它。在ReportProgress調用之後。如果能夠解決這個問題,那麼就會以人眼可以感知的速度報告進度。每秒不超過20次。 –

回答

0

看起來好像你的代碼是向後的。 UI線程應該更新UI,後臺線程應該執行長時間運行的任務(我想這就是EngTest_F())。解決這個問題的一種方法是使用System.Windows.Forms.Timer組件。設置Interval = 50左右的計時器,調用GetSicStatusMsg()更新UI。任務啓動時啓用計時器,並在任務完成時將其禁用。我不是BackgroundWorker的專家(我傾向於使用普通的Thread對象),但我敢打賭,只要任務進行,就需要調用ReportProgress;您的代碼只能調用一次ReportProgress。我建議在你的情況下使用一個普通的Thread +一個Timer,因爲你的非託管代碼可能很難調用BackgroundWorker.ReportProgress()。

+0

我認爲你是對的,製作一個自定義線程看起來像要走的路 - 背景工作者比方便更麻煩 –

+0

知道了!我最終做的是創建兩個線程,一個用於EngTest_F,一個用於GetSicStatusMsg。爲了在EngTest_F完成後停止GetSicStatusMsg線程,我剛剛創建了一個布爾變量'test_finished',它在EngTest_F完成時設置爲true。然後我使用test_finished作爲GetSicStatusMsg中while循環中的不變量,所以它運行到test_finished = true –