2012-10-08 139 views
3

这就是我在我的代码做的: 在BackgroundWorker的DoWork的事件中,我所做的:如何暂停和恢复BackgroundWorker?

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
      _busy.WaitOne(); 
       this.Invoke(new MethodInvoker(delegate { label2.Text = "Website To Crawl: "; })); 
       this.Invoke(new MethodInvoker(delegate { label4.Text = mainUrl; })); 
       webCrawler(mainUrl, levelsToCrawl, e); 


     } 

然后在暂停按钮单击事件我所做的:

private void button4_Click(object sender, EventArgs e) 
     { 
      _busy.Reset(); 
     } 

在恢复按钮点击事件我所做的:

private void button5_Click(object sender, EventArgs e) 
     { 
      _busy.Set(); 
     } 

但是当我点击来启动进程它不工作:

private void button1_Click(object sender, EventArgs e) 
     { 
      backgroundWorker1.RunWorkerAsync(); 
      button1.Enabled = false; 
      this.Text = "Processing..."; 
      label6.Text = "Processing..."; 
      label6.Visible = true; 
      button2.Enabled = false; 
      checkBox1.Enabled = false; 
      checkBox2.Enabled = false; 
      numericUpDown1.Enabled = false; 
      button3.Enabled = true; 
     } 

什么都没有发生,只有当我点击恢复按钮的过程开始,然后当我点击暂停按钮什么都没有发生。

我希望当我点击启动过程按钮时,它会定期启动背景工作,然后单击暂停按钮时它将暂停,恢复按钮将恢复。

我做错了什么?有人可以修复我的代码?

+1

打开的问题编辑... aaaand放弃:) – Reniuz

+0

只需修改工人可以访问的布尔值?我会在backgroundWorker中放弃这一点,而不是暂停线程本身。 – Aphelion

+0

Aphelion请给我一个例子谢谢。 –

回答

9

在你的BackgroundWorker线程代码中,你需要找到安全的地方来“暂停”执行。 ManualResetEvent是正确的编码方式。这等后期可能会有帮助: Is there a way to indefinitely pause a thread?

基本上,在几个选择的点在你的工作线程的代码要让它暂停,尝试插入:

_busy.WaitOne(Timeout.Infinite); 

而当你想暂停(从你的主线程)使用:

_busy.Reset(); 

并恢复:

_busy.Set(); 
0

你应该能够做到这一点使用ManualResetEvent这样的...

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    _busy.WaitOne(); 
    test(mainUrl, levelsToCrawl, e); 
} 

...然后当你要暂停的线程调用_busy.Reset() ...当你要重新启动它调用_busy.Set()

此外,您可以将_busy.WaitOne();放置在任何要暂停的位置。

0

我一直在寻找这个主题的答案,但我想出了我自己的解决方案,我只是想与你分享。希望这有效。

我有一个后台工作人员,我想暂停它,当我点击我的窗体的关闭按钮。询问“您即将取消流程”,因此应暂停流程。

在你的课堂上申报bool pauseWorker = false;

private void bgWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    while (condition) 
    { 
     if (pauseWorker == true) 
     { 
     while (pauseWorker == true) 
     { 
      if (pauseWorker == false) break; 
     } 
     } 
     else 
     { 
     //continue process... your code here 
     } 
    } 
} 

private void frmCmsnDownload_FormClosing(object sender, FormClosingEventArgs e) 
{ 
    if (bgWorker.IsBusy) 
    { 
     pauseWorker = true; //this will trigger the dowork event to loop that 
          //checks if pauseWorker is set to false 
     DiaglogResult x = MessageBox.Show("You are about cancel the process", "Close", MessageBoxButtons.YesNo); 
     if (x == DialogResult.Yes) bgWorker.CancelAsync(); 
     else 
     { 
     e.Cancel = true; 
     pauseWorker = false; //if the user click no 
           //the do work will continue the process 
     return; 
     } 
    } 
} 

因此,这里的主要解决方案是控制BGWorker的DoWork事件的布尔型声明。 希望这个解决方案可以帮助你解决问题。谢谢。

+0

这会消耗处理器周期,因为线程永远不会挂起。除非您知道暂停很短,否则最好使用锁定。 – Mgamerz

+0

你是对的。但它只是非常小的过程。而我找不到任何解决方案,这就是为什么我创建我的。除了我不知道如何使用锁定。 –

0

这个工作对我来说:

bool work = true; 
backgroundWorker1.WorkerReportsProgress = true; 
backgroundWorker1.DoWork += backgroundWorker1_DoWork; 
backgroundWorker1.ProgressChanged += myChangeFunction; 
backgroundWorker1.RunWorkerAsync(); 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    while (true && work) 
    { 
     // Your code here 

     backgroundWorker1.ReportProgress(0); 
     Thread.Sleep(1000); 
    } 
    e.Cancel = true; 
} 
private void myChangeFunction(object sender, ProgressChangedEventArgs e) 
{ 
    // Here you can change label.text or whatever thing the interface needs to change. 
} 
private void Stop() 
{ 
    work = false; 
} 
private void Start() 
{ 
    work = true; 
    backgroundWorker1.RunWorkerAsync(); 
} 

注:如果你想改变界面的东西,你必须把它放在myChangeFunction(),因为在DoWork的()函数将不工作。希望这可以帮助。