1

I am a relatively new c# user so forgive me if I have made some rookie mistakes. I have searched for a workaround to this error but am unable to find a implementation which works for me.

I have a worker thread which is basically looping while boolean isCalibrationActive is true. During the worker thread I have set up a callback to access a label in the main thread and change the text based on the worker thread. On the formclosing event in the main thread i set isCalibrationActive to false which should theoretically stop the loop in the worker thread. I get the error once i close the form.

Form Closing Event Code:

private void Form2_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (e.CloseReason == CloseReason.UserClosing)
        {
            DialogResult result = MessageBox.Show("The Calibration stage is not yet complete. Are you sure you want to exit?", "Dialog Title", MessageBoxButtons.YesNo);
            if (result == DialogResult.Yes)
            {
                isCalibrationActive = false;
                Thread.Sleep(10000);
                return;
            }
            else
            {
                e.Cancel = true;
            }
        }
        else
        {
            e.Cancel = true;
        }
    }

Worker Thread: EDIT: sorry i left my test code in there earlier.

    private void refreshXY()
    {
        var currentpath = new StringBuilder(255);

        //store current directory and set to dll directory.
        UnsafeNativeMethods.GetDllDirectory(currentpath.Length, currentpath);
        UnsafeNativeMethods.SetDllDirectory( "D:\\UI_still_in_progress\\Debug" );
        UnsafeNativeMethods.LoadLibrary("dllTESTER.dll");

        while (isCalibrationActive)
        {                
            xx = UnsafeNativeMethods.grabx();
            yy = UnsafeNativeMethods.graby();
            if (xx == 0) { xx = 0.001;}
            if (yy == 0) { yy = 0.001;}
            SetXlab(xx.ToString());
            SetYlab(yy.ToString());
        }
        //restore old directory
        UnsafeNativeMethods.SetDllDirectory(currentpath.ToString());
    }

The error occurs during the SetXlab or SetYlab functions which are basically identical. Also the reason i have it in another thread is because it is reading real time data from another application which needs to be consistently updated. This is shown below:

private void SetYlab(string yval)
    {
        // InvokeRequired required compares the thread ID of the
        // calling thread to the thread ID of the creating thread.
        // If these threads are different, it returns true.
        if (this.yshow.InvokeRequired)
        {
            SetTextCallback yD = new SetTextCallback(SetYlab);
            if (isCalibrationActive) { this.Invoke(yD, new object[] { yval }); }
        }
        else
        {
            this.yshow.Text = yval;
        }
    }

Specifically the line this.Invoke(yD, new object[] { yval }); } is what causes the error. Any ideas how I can avoid this?

Raps
  • 65
  • 3
  • Are `grabx` and `graby` reasonably quick-running methods? Like generally less than 5 ms, rarely more than 50 ms, and never more than a second? – Dax Fohl Sep 02 '15 at 03:34
  • (And rookie mistakes--C# "de-facto" coding standards uses PascalCase for methods and properties, just FYI; feel free to do what you want) – Dax Fohl Sep 02 '15 at 03:40

1 Answers1

0

I'd probably use a System.Windows.Forms (SWF) Timer called calGuiUpdateTimer, with Tick function something like this

        xx = 0;
        yy = 100;
        xx = UnsafeNativeMethods.grabx();
        yy = UnsafeNativeMethods.graby();
        if (xx == 0) { xx = 0.001;}
        if (yy == 0) { yy = 0.001;}
        this.xshow.Text = xx.ToString();
        this.yshow.Text = yy.ToString();

And then get rid of isCalibrationActive and instead replace it with calGuiUpdateTimer.Enabled.

A SWF Timer always runs on the GUI thread, so that way you don't have to worry about switching threads at all; you can get rid of all those functions with all that InvokeRequired junk completely. Makes your stuff much easier.

That said, if grabx or graby are potentially slow-running functions, this option will make your GUI stutter and a SWF timer would be unacceptable. In that case, continue using your background thread solution and see Avoid calling Invoke when the control is disposed for guidance (and also see https://stackoverflow.com/a/661662/171121 to simplify your callback).

Community
  • 1
  • 1
Dax Fohl
  • 10,654
  • 6
  • 46
  • 90
  • Thank you, I realised i could have the worker thread updating the global variables, and the timer.tick event updating the form :) – Raps Sep 04 '15 at 03:35