2013-04-17 107 views
2

我的应用程序使用后台工作人员去做一些循环内的工作。我拥有它,以便在每次循环迭代时检查取消挂起是否为真,如果是,则打开循环。一切OK,我的应用程序在完成循环的当前迭代后停止处理。问题是我认为后台工作人员仍在运行 - 如果我点击该按钮重新开始处理,我会收到一个错误消息,说明后台工作人员正在忙碌。停止后台工作人员

我打算处理工作人员,但随后在表单运行时创建,因此如果我处理它,则不会再开始再次工作。我真正想要做的是告诉后台工作者它已经完成,如果我点击一个“停止处理”按钮,所以当我点击开始按钮时,它就可以再次开始处理了!

我要试试这个:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    while (!backgroundWorker1.CancellationPending) 
    { 
     // Start processing in a background thread so the GUI remains responsive, 
     // pass in the name of the text file produced by 
     // PFDR FilenameLogic(txtLetterType.Text); 
    } 
} 
+0

你是在等'RunWorkerCompleted'事件用于启动*开始处理*按钮? –

+0

“我这样做,以便在每次循环迭代时,它检查取消挂起是否为真,如果是,则打开循环。”当取消挂起为真时,您是否将DoWorkEventArgs e parametrs Cancel属性设置为true? => e.Cancel = true; – boli

回答

5

与Marc Gravell一样的答案,但你似乎没有遵循。

您是否正在设置e.cancel = true?

 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
      BackgroundWorker worker = sender as BackgroundWorker; 

      for (int i = 1; i <= 10; i++) 
      { 
       if (worker.CancellationPending == true) 
       { 
        e.Cancel = true; 
        break; 
       } 
       else 
       { 
        // Perform a time consuming operation and report progress. 
        System.Threading.Thread.Sleep(500); 
        worker.ReportProgress(i * 10); 
       } 
      } 
     } 
6

当您创建的工人,设置worker.WorkerSupportsCancellationtrue。现在里面DoWork处理程序,你必须定期(最常见的,在一些循环的开始等)检查worker.CancellationPending - 如果它是真的,设置e.Cancel = true;(这样你可以区分完成与取消),清理,并退出(return;)。现在您的取消按钮可以调用worker.CancelAsync();,它会采取适当的行动。

+0

那么我如何定期检查状态? 我打算用这样的:(!backgroundWorker1.CancellationPending) 私人无效backgroundWorker1_DoWork(对象发件人,DoWorkEventArgs E) { 而 {// 在后台线程开始处理所以GUI保持响应,通过在名称由PFDR产生的文本文件 FilenameLogic(txtLetterType.Text); } } 但它会工作吗? – user1779064

+0

@ user1779064没有您的处理程序的具体示例,很难回答。但不要循环*直到它被取消 - 否则它永远不会完成*通常*(如果你明白我的意思)。通常,工作人员正在处理已知数量的工作 - 通常涉及某种“for”或“foreach”循环 - 其中最重要的是检查取消的理想位置。 –

0

我似乎已经解决了这个错误 - 在BackgroundWorker的DoWork的方法,我把在一段时间CancelPending是不正确的,当它是真实的我设置e.Cancel =真现在似乎好工作!

1

我很难找到一个很好的方式如何取消一个BackgroundWorker的停止按钮

我的应用程序是这样的,两个按钮和一个进度:

enter image description here

按下停止按钮后,它看起来像这样:

enter image description here

对于开始按钮点击方法,代码检查BGW是否忙碌。如果无法启动BGW:

private void btnStart_Click(object sender, EventArgs e) 
    { 


     //BGW 
     if (!backgroundWorker1.IsBusy) 
     { 

      backgroundWorker1.RunWorkerAsync(); 

     } 



    } 

停止按钮调用下面的方法,它设置一个标志,CancellationPending为true:

 private void btnStop_Click(object sender, EventArgs e) 
    { 
     backgroundWorker1.CancelAsync(); 
    } 

这个标志可以在backgroundWorker1 _DoWork使用方法,它负责处理高耗时的功能:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     for (int i = 0; i <= 100; i++) 
     { 

      backgroundWorker1.ReportProgress(i); 
      Thread.Sleep(100); 



      if (backgroundWorker1.CancellationPending && backgroundWorker1.IsBusy) 
      { 
       e.Cancel = true; 
       return; 
      } 
     } 
    } 

现在出现了棘手的部分,因为在关闭额外的线程之前,如果它被取消或不被取消,你必须检查后台对象中的对象012!否则你会得到一个错误

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     int i = 0; 

     if (!e.Cancelled) 
     { 
      i = (int)(e.Result); 
     } 
     else 
     { 
      i = 0; 
     } 

     // Check to see if an error occurred in the 
     // background process. 
     if (e.Error != null) 
     { 
      MessageBox.Show(e.Error.Message); 
      return; 
     } 

     // Check to see if the background process was cancelled. 
     if (e.Cancelled) 
     { 
      MessageBox.Show("Processing cancelled."); 
      return; 
     } 

     // Everything completed normally. 
     // process the response using e.Result 
     MessageBox.Show("Processing is complete."); 

    } 

的额外信息: 不要忘记设置这些BackgroundWorker的标志:

  //Set WorkerReportsProgress true - otherwise no ProgressChanged active 
     backgroundWorker1.WorkerReportsProgress = true; 
     backgroundWorker1.WorkerSupportsCancellation = true; 

如果这个小教程是有帮助 - >赞许