[.net] C# - Threading and Events Problem

Started by
4 comments, last by CyberJay82 16 years, 6 months ago
I have a serial port device which I can get certain information from it, for example a voltage. My problem lies with threading and the end programmer using my events to display the info given to them via the events they subscribe to. I have a public interface which inheirts from my class that actually does the reading from the serial port. This base class has a method that is called each time a voltage is read from the serial port. This is done via a thread that just polls the serial port checking for voltage data. My thread function in a simple form looks like this:

public void TaskFunction()
{
	if(IsVoltageData)
	{
		OnVolts();
	}
}




The OnVolts function looks like this:

protected override void OnVolts()
{
	VoltmeterHandler voltsdata = OnVoltsData;
	if (voltsdata != null)
	{
		voltsdata.Invoke(this, new VoltmeterArgs(GetVoltage()));
	}
}




The end programmer will use my public interface which has the following Event Arguments, delegate, and event:

public class VoltmeterArgs : EventArgs
    {
        public double m_Data;

        public VoltmeterArgs(double data)
        {
            m_Data = data;
        }
    }

public delegate void VoltmeterHandler(object sender, VoltmeterArgs e);

public event VoltmeterHandler OnVoltsData;




Now that end programmer would hook up to that event (OnVoltsData) and use it for example to display the voltage to the user via a textbox or something. Here lies my problem. When ever I do this in my test app:

public void VoltMeter_OnVoltsData(object sender, VoltmeterArgs e)
{
     txtVoltage.Text = e.m_Data.ToString();
}




I still get this error: "Cross-thread operation not valid: Control 'txtVoltage' accessed from a thread other than the thread it was created on." I guess I am missing something or don't understand something. I thought when you invoked the event it would then fire the event on the thread it was created on. Any ideas, options, links, information I can read to help sort this issue I am having out?
Its not a bug, its a feature!!
Advertisement
This is an error that was introduced in VS2005 and can actually be disabled so that it will compile. However, it's better to actually go with the solution: you can't access controls from a thread other than the one on which they are created. When you invoke the event delegate, the listeners are invoked on the current thread.

The solution, thankfully is simple.

public void VoltMeter_OnVoltsData(object sender, VoltmeterArgs e){     if (txtVoltage.InvokeRequired)         txtVoltage.Invoke(VoltMeter_OnVoltsData(sender, e));     else         txtVoltage.Text = e.m_Data.ToString();}


In this case, however, rather than playing with threads directly, you may be better off using a BackgroundWorker and handling its RunWorkerCompleted event (you pass your data in the Result field of RunWorkerCompletedEventArgs).

EDIT: Closed missed bracket for function call, added supplementary links.
[TheUnbeliever]
Sorry, I should say it compiles and runs, but throws an exception with that error.

I know that using invoke on the textbox control would be a solution, but I was hoping to hide that from the end programmer and just allow them to use the textbox control like normal by just setting it's text.
Its not a bug, its a feature!!
Consider using BackgroundWorker internally, instead of Thread directly, as it doesn't require the use of Control.Invoke.
Anthony Umfer
Quote:Original post by CyberJay82
Sorry, I should say it compiles and runs, but throws an exception with that error.


Sorry, I wasn't very accurate. This would require considerable analysis of the code to produce a compile-time error; I mean that the error was introduced with that version of .NET (2.0?).

Quote:I know that using invoke on the textbox control would be a solution, but I was hoping to hide that from the end programmer and just allow them to use the textbox control like normal by just setting it's text.


About your easiest option then, as I and the above poster have said, is to use a BackgroundWorker.

[TheUnbeliever]
Alright, thanks guys for the info.
Its not a bug, its a feature!!

This topic is closed to new replies.

Advertisement