2012-10-08 61 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的()函數將不工作。希望這可以幫助。