0

In Form1 top i added this:

bool completed;
AutoResetEvent autoreset;

In the constructor i did:

completed = false;
autoreset = new AutoResetEvent(false);

In the backgroundworker DoWork event i did:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            while (true)
            {
                completed = true;
                if ((worker.CancellationPending == true))
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    if (tempCpuValue >= (float?)nud1.Value || tempGpuValue >= (float?)nud1.Value)
                    {
                        soundPlay = true;
                        NudgeMe();
                    }
                    else
                    {
                        soundPlay = false;
                        stop_alarm = true;

                    }

                    tempCpuValue = Core.cpuView(pauseContinueDoWork,cpu,this,data,tempCpuValue,button1);
                    tempGpuValue = Core.gpuView(pauseContinueDoWork,data,tempGpuValue,button1);
                    this.Invoke(new Action(() => data = new List<string>()));
                    tempCpuValue = Core.cpuView(pauseContinueDoWork, cpu, this, data, tempCpuValue, button1);
                    tempGpuValue = Core.gpuView(pauseContinueDoWork, data, tempGpuValue, button1);
                    this.Invoke(new Action(() => listBox1.DataSource = null));
                    this.Invoke(new Action(() => listBox1.DataSource = data));



                    //listBox1.DataSource = data;

                }
            }
            autoreset.Set();
        }

Then in the Form1 closing event i did:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (MessageBox.Show("Are you Sure you want to Exit. Click Yes to Confirm and No to continue", "WinForm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
            {
                e.Cancel = true;
            }
            else
            {
                if (completed == true)
                {
                    this.backgroundWorker1.CancelAsync();
                    autoreset.WaitOne();
                }
            }


        }

When it's doing the WaitOne() the form just back show up in the middle and the program is freezing all i can do is in the visual studio Debug>Stop Debugging

I wanted to do it to aovid exceptions im getting sometimes RaceOnRCWCleanup something about multi threadings.

And sometimes when closing the program i got on another class this exception:

System.ObjectDisposedException was unhandled by user code
  HResult=-2146232798
  Message=Cannot access a disposed object.
Object name: 'Form1'.
  Source=System.Windows.Forms
  ObjectName=Form1
  StackTrace:
       at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
       at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
       at System.Windows.Forms.Control.Invoke(Delegate method)
       at HardwareMonitoring.Core.cpuView(Boolean pause, CpuTemperature cpuTemp, Form1 f1, List`1 myData, Nullable`1 myCpuTemp, Button b1) in d:\C-Sharp\HardwareMonitoring\HardwareMonitoring\Hardwaremonitoring\Core.cs:line 55
       at HardwareMonitoring.Form1.backgroundWorker1_DoWork(Object sender, DoWorkEventArgs e) in d:\C-Sharp\HardwareMonitoring\HardwareMonitoring\Hardwaremonitoring\Form1.cs:line 427
       at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
       at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)
  InnerException: 

Like the form1 disposed before the backgroundworker finished the job and the backgrounddworker dowork event is using this class methods.

user2760148
  • 427
  • 2
  • 9
  • 19

2 Answers2

2

Suppose Bgw is you backgroundworker first you will set :

Bgw.WorkerSupportsCancellation = true;  

then in you DoWork delegate you will have to check whether Bgw.CancellationPending is true or false.

If it is true that means backgroundworker has been canceled and you will have to abort the function if not continue as it is.

Xaruth
  • 4,034
  • 3
  • 19
  • 26
0

Try this:

void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    while (!backgroundWorker1.CancellationPending)
    {
        if (tempCpuValue >= (float?)nud1.Value || tempGpuValue >= (float?)nud1.Value)
        {
            soundPlay = true;
            NudgeMe();
        }
        else
        {
            soundPlay = false;
            stop_alarm = true;

        }

        tempCpuValue = Core.cpuView(pauseContinueDoWork, cpu, this, data, tempCpuValue, button1);
        tempGpuValue = Core.gpuView(pauseContinueDoWork, data, tempGpuValue, button1);
        this.BeginInvoke(new Action(() => data = new List<string>()));
        tempCpuValue = Core.cpuView(pauseContinueDoWork, cpu, this, data, tempCpuValue, button1);
        tempGpuValue = Core.gpuView(pauseContinueDoWork, data, tempGpuValue, button1);
        this.BeginInvoke(new Action(() => listBox1.DataSource = null));
        this.BeginInvoke(new Action(() => listBox1.DataSource = data));
    }

    completed = true;

    autoreset.Set();
}

void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (MessageBox.Show("Are you Sure you want to Exit. Click Yes to Confirm and No to continue", "WinForm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
    {
        e.Cancel = true;
    }
    else
    {
        if (!completed)
        {
            this.backgroundWorker1.CancelAsync();
            Hide(); // hide the form while waiting for the bw to terminate
            autoreset.WaitOne();
        }
    }
}

I've changed the calls from Invoke to BeginInvoke this should mitigate your problems.

Alessandro D'Andria
  • 8,663
  • 2
  • 36
  • 32