2017-06-28 52 views
0

在我的小測試程序中,我想檢查機器的某些部分,同時更新標籤和進度條(基本上是一個啓動窗體,通知用戶關於機器啓動的進度)。 爲此,我已經閱讀了關於在後臺工作中添加東西以及通過ReportProgress更新UI的信息。這工作正常。通過在WinForm中顯示UI中的消息框(來自backgroundworker)來阻止Workerthread

所有部件檢查都是在do-while-loop內完成的,只有在零件檢測成功時纔會執行。如果一個零件檢測成功,則循環結束,並且工作線程移動到下一個零件的下一個循環,直到檢查完所有零件。

現在,如果一個部分有缺陷,並且測試不成功,我想顯示一個MessageBox,通知用戶有關缺陷。在這樣做的時候,WorkerThread應該停止,等待用戶按「重試」或「確定」。到目前爲止,無論是新聞發佈會從一開始就開始當前的do-while-loop,直到問題得到解決。 如果我只在我的循環中放入MessageBox.Show(「test」),它會在完成backgroundthread結束後顯示,並在顯示消息框後再次啓動後臺線程。

這裏我的代碼:

namespace USBSerialTest 
{ 
public partial class test1 : Form 
{ 
    private int check; 
    private int Progress; 

    private byte[] Check_byte_Board1 = { 0x02, 0x01, 0x64, 0x06, 0x00, 0x00, 0x00, 0x80, 0xed }; 
    private byte[] Check_byte_Board2 = { 0x02, 0x01, 0x64, 0x06, 0x00, 0x00, 0x00, 0x81, 0xee }; 

    public test1() 
    { 
     InitializeComponent(); 
     Shown += new EventHandler(test1_LoadForm); 
     backgroundWorker1.WorkerReportsProgress = true; 
     backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork); 
     backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged); 

     //backgroundWorker1.ProgressChanged += ShowWarning; Not working 
    } 
    void test1_LoadForm(object sender, EventArgs e) 
    { 
     backgroundWorker1.RunWorkerAsync(); 
    } 

    void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     Progress = 0; 
     backgroundWorker1.ReportProgress(Progress, "Checking for Board Function"); 
     do               //check if Board retruns an error 
     { 
      Motor.Instance.Check_Board(); 
      if (Motor.Instance.buf.SequenceEqual(Check_byte_Board1) || Motor.Instance.buf.SequenceEqual(Check_byte_Board2)) 
      { 
       check = 1; 
       Progress += 10; 
       //MessageBox.Show("test"); not working, just for testing here 
       backgroundWorker1.ReportProgress(Progress, "Checking for Board Function"); 

      } 
      else 
      { 
       //here is the important part, when there is an error, I want to display the warning message 
       //and start the do-while loop from the start, all other message boxes where just to 
       //test around if the general principle works 
       DialogResult result = MessageBox.Show("Boarddriver produce Errorcode ... Please Consult"); 
       if (result == DialogResult.Retry) 
       { 
        check = 0; 
       } 
       else 
       { 
        check = 0; 
       } 
      } 
     } while (check != 1); 
     backgroundWorker1.ReportProgress(Progress, "Succes");   
    } 
    // Back on the 'UI' thread so we can update the progress bar 
    void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     progressBar1.Value = e.ProgressPercentage; 
     label1.Text = e.UserState.ToString(); 
     //MessageBox.Show(e.UserState.ToString()); not working 
    } 

    private static void ShowWarning(object sender, ProgressChangedEventArgs e) 
    { 
     MessageBox.Show("test box"); //not working, displays a Messagebox each time 
     //ProgressChanged is triggered, but does not block the worker thread. 
    } 
} 
} 

所以,我怎麼能停止與一個消息框,警告工作者線程,並繼續它(或恢復電流回路)?

+0

我知道這個問題以前曾以類似的方式提出過,那就是我得到了我的「試用解決方案」,這是我玩過的。我還讀到它並沒有真正批准用MessageBoxes來發送用戶郵件,但我需要某種用戶輸入(其他粗略的想法是將標籤更改爲警告,並在錯誤事件觸發時顯示/隱藏按鈕 – Chris

+0

你的問題很混亂,也不清楚,用你發佈的代碼,在DoWork事件處理程序中調用'MessageBox.Show()'的地方,實際上應該立即顯示消息框,代碼應該等待在循環中的Show()調用中,直到用戶已經解除了消息框,這似乎符合你的標準,除此之外,還不清楚你的循環實際在做什麼;它似乎並沒有執行多個測試,正如你的敘述所描述的那樣,並且似乎沒有任何機制可以根據用戶輸入或其他方式重新啓動失敗測試。 –

+0

個人而言,我不會使用'BackgroundWorker'。它的時間很不錯,但它已經被取代b y'Task.Run()'和相關的框架和語言特性。我猜想解決方案的最好方法是使你的'LoadForm'事件處理程序'async',使用'Task.Run()'來調用每個測試,並將所有的UI處理直接放在'LoadForm事件處理程序方法。但有了這樣一個令人困惑的問題,我不想嘗試發表一個完整的答案。如果你想要的話,請改善你的問題。 –

回答

0

您可以使用ReportProgress()方法來報告測試失敗並攔截ProgressChanged事件中您可以顯示消息框的問題。

要使工作線程等待用戶響應,可以使用同步對象,例如AutoResetEvent

namespace USBSerialTest 
{ 
    public partial class test1 : Form 
    { 
     private int check; 
     private int Progress; 
     private MessageBoxResult UserDecision; 
     private AutoResetEvent UserDecidedEvent = new AutoResetEvent(false); 
     private string ErrorCode; 

     private byte[] Check_byte_Board1 = { 0x02, 0x01, 0x64, 0x06, 0x00, 0x00, 0x00, 0x80, 0xed }; 
     private byte[] Check_byte_Board2 = { 0x02, 0x01, 0x64, 0x06, 0x00, 0x00, 0x00, 0x81, 0xee }; 

     public test1() 
     { 
      InitializeComponent(); 
      Shown += new EventHandler(test1_LoadForm); 
      backgroundWorker1.WorkerReportsProgress = true; 
      backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork); 
      backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged); 

      //backgroundWorker1.ProgressChanged += ShowWarning; Not working 
     } 
     void test1_LoadForm(object sender, EventArgs e) 
     { 
      backgroundWorker1.RunWorkerAsync(); 
     } 

     void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
      Progress = 0; 
      backgroundWorker1.ReportProgress(Progress, "Checking for Board Function"); 
      do               //check if Board retruns an error 
      { 
       Motor.Instance.Check_Board(); 
       if (Motor.Instance.buf.SequenceEqual(Check_byte_Board1) || Motor.Instance.buf.SequenceEqual(Check_byte_Board2)) 
       { 
        check = 1; 
        Progress += 10; 
        //MessageBox.Show("test"); not working, just for testing here 
        backgroundWorker1.ReportProgress(Progress, "Checking for Board Function"); 

       } 
       else 
       { 
        //here is the important part, when there is an error, I want to display the warning message 
        //and start the do-while loop from the start, all other message boxes where just to 
        //test around if the general principle works 
        ErrorCode = "Boarddriver produce Errorcode ... Please Consult"; 
        backgroundWorker1.ReportProgress(Progress, ErrorCode); 

        UserDecidedEvent.WaitOne(); 

        if (UserDecision != DialogResult.Retry) 
        { 
         check = 1; 
         // Rewind checking of the board here to try the same 
         // action again when calling Motor.Instance.Check_Board() 
        } 
        else 
        { 
         check = 0; 
        } 
       } 
      } while (check != 1); 
      backgroundWorker1.ReportProgress(Progress, "Succes"); 
     } 
     // Back on the 'UI' thread so we can update the progress bar 
     void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      if (e.UserState == ErrorCode) 
      { 
       UserDecision = MessageBox.Show("Boarddriver produce Errorcode ... Please Consult"); 
       UserDecidedEvent.Set(); 
      } 
      else 
      { 
       progressBar1.Value = e.ProgressPercentage; 
       label1.Text = e.UserState.ToString(); 
      } 
     } 
    } 
} 
+0

感謝您的快速回答。雖然這對我來說很有意義,但當我嘗試在我的代碼中實現該示例時,仍存在兩個問題。首先是,「私人MessageBoxResult UserDecision;」不存在(特別是MessageBoxResult)。以下我用DialogResult Userdecision試了一下; 第二個是,當我運行帶有模擬缺陷的代碼(斷開板子)時,顯示MessageBox,但如果我按重試,背景工作器將從頭再次開始。並且只有當我第二次按下它時才終止(在修復缺陷之後) – Chris

+0

爲了讓工作線程真正重試最後一個動作,您需要以某種方式告訴'Motor.Instance'對象或'Check_Board()'方法來重試它。 –

相關問題