2017-06-28 49 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()'方法来重试它。 –

相关问题