简体   繁体   中英

c# unexpected backgroundWorker behaviour

I have attached a backgroundWorker component to my main form which runs a parallel task of capturing the screen for an animated gif. The worker's function has a while loop that runs until I use CancelAsync() on the worker, at which point it exits the loop, does some other things like saving the gif file and so on and returns some results to the UI thread.

private bool capturing = false;

public MainForm()
{
    InitializeComponent();
    backgroundWorker.DoWork += backgroundWorker_DoWork;
    backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
    backgroundWorker.WorkerSupportsCancellation = true;
}

private void captureBtn_Click(object sender, EventArgs e)
{
    Debug.WriteLine("Button clicked");
    if (capturing) { return; }
    if (!backgroundWorker.IsBusy)
    {
        backgroundWorker.RunWorkerAsync();
    }
}

private void stopCaptureBtn_Click(object sender, EventArgs e)
{
    if (backgroundWorker.IsBusy)
    {
        backgroundWorker.CancelAsync();
    }
}

private void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    capturing = true;
    Debug.WriteLine("DoWork running");

    while (!backgroundWorker.CancellationPending)
    {
        Debug.WriteLine("Capturing frame {0}", frames);
        //do the capturing to memory stream
    }

    Debug.WriteLine("DoWork cancelled");

    //do some other things like saving the gif etc
    e.Result = someResult;
}

private void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
    Debug.WriteLine("RunWorkerCompleted running");
    capturing = false;
    //does something with the e.Result
}

My console output during a normal test is something like this:

Button clicked
DoWork running
Capturing frame 0
Capturing frame 1
Capturing frame 2
Capturing frame 3
Capturing frame 4
Capturing frame 5
Cancel button clicked
DoWork cancelled
The thread 0x2e4c has exited with code 0 (0x0).
DoWork running
DoWork cancelled
The thread 0x1010 has exited with code 0 (0x0).
RunWorkerCompleted running

The function seems to be running twice, I can see 2 separate threads exiting and also I don't seem to get any results from capturing. If I set a breakpoint inside the backgroundWorker_DoWork function and continue later, the first run does the capturing normally. What could be going on?

Its getting called twice because binding the event second time right after InitializeComponent(). Just comment those lines and it should work fine. Here's the same example without the issue of running twice.

Sample Output ... ... ... Capturing frame 2632 Capturing frame 2633 Capturing frame 2634 DoWork cancelled RunWorkerCompleted running

public partial class Form1 : Form
    {
        private bool capturing = false;
        public Form1()
        {
            InitializeComponent();
            backgroundWorker1.WorkerSupportsCancellation = true;

  // Don't need to re-bind
            //backgroundWorker1.DoWork += backgroundWorker1_DoWork;
            //backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
            //backgroundWorker1.WorkerSupportsCancellation = true;
        }



private void captureBtn_Click(object sender, EventArgs e)
        {
            Debug.WriteLine("Button clicked");
            if (capturing) { return; }
            if (!backgroundWorker1.IsBusy)
            {
                backgroundWorker1.RunWorkerAsync();
            }
        }

        private void stopCaptureBtn_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.IsBusy)
            {
                backgroundWorker1.CancelAsync();
            }
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            capturing = true;
            Debug.WriteLine("DoWork running");
            int frames = 1;

            while (!backgroundWorker1.CancellationPending)
            {
                Debug.WriteLine("Capturing frame {0}", frames);
                //do the capturing to memory stream
                frames++;
            }

            Debug.WriteLine("DoWork cancelled");

            //do some other things like saving the gif etc
            //e.Result = someResult;
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Debug.WriteLine("RunWorkerCompleted running");
            capturing = false;
            //does something with the e.Result
        }

The thread 0x3108 has exited with code 0 (0x0) means there was no error. While reading or writing the big data, you should divide it into parts. Otherwise, you cannot progress. Your current while loop is disabled when writing to memory stream. so your backgroundWorker_DoWork method should be like this :

    private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        var worker = (BackgroundWorker)sender;

        // this is an example file
        string filePath = @"C:\file.gif";

        // it determines how many bytes of data will be received from the stream each time.
        byte[] buffer = new byte[4096];
        int byteCount = 0;

        // we are preparing to read stream.
        using (FileStream fs = new FileStream(filePath, FileMode.Open, System.IO.FileAccess.Read))
        using (MemoryStream ms = new MemoryStream())
        {
            // read the stream bytes and fill buffer
            while ((byteCount = fs.Read(buffer, 0, buffer.Length)) > 0)
            {
                // if the task was canceled
                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                    break;
                }

                // write buffer to memory stream
                ms.Write(buffer, 0, byteCount);
            }
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM