מני מנחם
מני מנחם

Reputation: 235

How can i pause/resume a loop in a backgroundworker?

In the top of form1

private System.Threading.ManualResetEvent _busy = new System.Threading.ManualResetEvent(false);
private System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();

A button click event that start the backgroundworker and the timer

private void startButton_Click(object sender, EventArgs e)
        {
            startButton.Enabled = false;
            stopButton.Enabled = true;
            timer1.Start();
            if (!backgroundWorker1.IsBusy)
                backgroundWorker1.RunWorkerAsync();
        }

Dowork event

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            _stopwatch.Restart();
            DirSearch(@"d:\c-sharp", "*.cs", "Form1", worker, e);
            _stopwatch.Stop();
        }

DirSearch method

private void DirSearch(string root, string filesExtension,string textToSearch, BackgroundWorker worker, DoWorkEventArgs e)
        {
            int numberoffiles = 0;
            int numberofdirs = 0;
            string[] filePaths = Directory.GetFiles(root, filesExtension, SearchOption.AllDirectories);
            for (int i = 0; i < filePaths.Length; i++)
            {
                _busy.WaitOne();
                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    return;
                }

                List<MyProgress> prog = new List<MyProgress>();
                int var = File.ReadAllText(filePaths[i]).Contains(textToSearch) ? 1 : 0;
                if (var == 1)
                {
                    string filename = filePaths[i];
                    numberoffiles ++;
                    prog.Add(new MyProgress { Report1 = filename, Report2 = numberoffiles.ToString() });
                    backgroundWorker1.ReportProgress(0, prog);
                    Thread.Sleep(100);
                }
                numberofdirs ++;
                label1.Invoke((MethodInvoker)delegate
                            {
                                label1.Text = numberofdirs.ToString();
                                label1.Visible = true;
                            });
            }
        }

Button click event for pause/resume

private void pauseresumeButton_Click(object sender, EventArgs e)
        {
            if (pauseresumeButton.Text == "Resume")
            {
                pauseresumeButton.Text = "Pause";
                _busy.Set();
            }
            else
            {
                pauseresumeButton.Text = "Resume";
                _busy.Reset();
            }
        }

The pauseresumeButton text in designer is set to "Pause"

And the problem is that the _busy.WaitOne(); inside the DirSearch make it that when i click the start button only the timer is running. Then i need to click the pauseresumeButton to start it like resume it.

What i want to do is when i click the start button everything will start the timer and the DirSearch. And then if i click on the pauseresumeButton to pause the backgroundworker the timer and the DirSearch operation and another click on pauseresumeButton to resume from where it all stopped.

Upvotes: 0

Views: 2382

Answers (1)

Ivan Stoev
Ivan Stoev

Reputation: 205849

Since starting the worker is similar to resuming, you can move the common part to a separate method:

private void SetWorkerMode(bool running)
{
    if (running)
    {
        pauseresumeButton.Text = "Pause";
        _busy.Set();
    }
    else
    {
        pauseresumeButton.Text = "Resume";
        _busy.Reset();
    }
}

and then use it from both places:

private void startButton_Click(object sender, EventArgs e)
{
    // ...
    if (!backgroundWorker1.IsBusy)
    {
        SetWorkerMode(true);
        backgroundWorker1.RunWorkerAsync();
    }
}

private void pauseresumeButton_Click(object sender, EventArgs e)
{
    SetWorkerMode(pauseresumeButton.Text == "Resume");
}

I guess now you can see what's the issue with your current code - the pauseresumeButton is showing "Pause", but the _busy is not set.

Upvotes: 2

Related Questions