6

这就是我在代码中的做法: 在 backgroundWorker DoWork 事件中,我做了:

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;
        }

只有当我单击恢复按钮时才会发生任何事情,然后当我单击暂停按钮时不会发生任何事情。

我希望当我单击启动进程按钮时,它将定期启动 backgroundWorker,然后当单击暂停按钮时,它将暂停,而恢复按钮将恢复。

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

4

5 回答 5

11

在您的 BackgroundWorker 线程代码中,您需要找到可以安全“暂停”执行的位置。ManualResetEvent 是正确的编码方式。这篇其他帖子可能会有所帮助: 有没有办法无限期地暂停一个线程?

基本上,在您希望允许它暂停的工作线程代码中的几个选择点中,尝试插入:

_busy.WaitOne(Timeout.Infinite);

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

_busy.Reset();

并继续:

_busy.Set();
于 2012-10-08T11:15:32.473 回答
0

你应该能够使用ManualResetEvent这样的...

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

...然后当你想暂停线程调用_busy.Reset()时......以及当你想重新启动它时调用_busy.Set()

此外,您可以放置_busy.WaitOne();​​任何您想暂停的地方。

于 2012-10-08T11:16:26.557 回答
0

我使用一个简单的类,它利用 System.Thread.Monitor 和 lock()...

public class ThreadPauseState {
    private object _lock = new object();
    private bool _paused = false;

    public bool Paused {
        get { return _paused; }
        set {
            if(_paused != value) {
                if(value) {
                    Monitor.Enter(_lock);
                    _paused = true;
                } else {
                    _paused = false;
                    Monitor.Exit(_lock);
                }
            }
        }
    }

    public void Wait() {
        lock(_lock) { }
    }
}

使用它非常简单...

private ThreadPauseState _state = new ThreadPauseState();

private void btnPause_Click(object sender, EventArgs e) {
    _state.Paused = true;
}

private void btnResume_Click(object sender, EventArgs e) {
    _state.Paused = false;
}

private void btnCancel_Click(object sender, EventArgs e) {
    backgroundWorker1.CancelAsync();
    _state.Paused = false; // needed if you cancel while paused
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
    var worker = (BackgroundWorker)sender;
    for(var _ = 0; _ < 100; _++) {
        _state.Wait();
        if(worker.CancellationPending) return;
        Thread.Sleep(100); // or whatever your work is
    }
}
于 2018-12-01T09:05:10.890 回答
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 事件的布尔声明。希望这个解决方案可以帮助您解决问题。谢谢你。

于 2016-11-26T03:54:53.627 回答
-1

这对我有用:

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() 函数中将不起作用。希望这可以帮助。

于 2017-03-18T17:06:15.627 回答