blah blah blah is here! blah blah » Close

up0down
link

I have some code that checks for a device connection...

internal sealed class FC_Device
{

//...... Deleted for clarity

public delegate void DeviceConnectedHandler ();
public event DeviceConnectedHandler DeviceConnected;

public delegate void DeviceDisconnectedHandler();
public event DeviceDisconnectedHandler DeviceDisconnected;

private void CheckConnection()
{
//Search for a device with description of device
ManagementObjectSearcher mos = new ManagementObjectSearcher("Select * from Win32_PnPEntity where Description like 'MyDevice%'");

//Raise connected event if device detected (only once)
if (mos.Get().Count > 0 && connected == false)
{
connected = true;
DeviceConnected();
}
//Raise the disconnected event if device no longer present (only once)
else if (mos.Get().Count == 0 && connected == true)
{
connected = false;
DeviceDisconnected();
}
}


//...... Deleted for clarity

}


Then in my main window I have registered the event from the class above...

//Register connect/disconnect events
fc.DeviceConnected +=new FC_Device.DeviceConnectedHandler(fc_DeviceConnected);
fc.DeviceDisconnected +=new FC_Device.DeviceDisconnectedHandler(fc_DeviceDisconnected);

private void fc_DeviceConnected()
{
this.LabelConnectionStatus.Content = "Connected";
}

private void fc_DeviceDisconnected()
{
this.LabelConnectionStatus.Content = "Not Connected";
}


The program runs, finds the device which triggers the event. However, when executing...

this.LabelConnectionStatus.Content = "Connected";


I receive an exception stating "The calling thread cannot access this object because a different thread owns it.

Why? And why does this not happen for other events? For example, a combo box selection changed event is fired and I can change label content. I am guessing because they are 'owned' by the same thread. So, this leads to another question. Where was this additional thread created (I didn't explicitly create any threads).

last answered 2 years ago

1 answers

link

If you're polling the connection status using a System.Timers.Timer, then the Elapsed event will occur on a background thread which may explain the error.

To get rid of it, you need to marshal the call back to the UI thread. I'd try (WPF assumed):

private void fc_DeviceConnected()
{
this.LabelConnectionStatus.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal,
new Action(
delegate()
{
this.LabelConnectionStatus.Content = "Connected";
}
)
);
}

with similar code for the other eventhandler.

eeboy
499

Since adding this bit of code I occasionally get a 'RaceOnRCWCleanup was detected' exception. The bit of documentation from the MSDN doesn't help me at all but does seem to reinforce that the problem is related to Dispatcher.Invoke. Thoughts?

vulpes
17279

If you change Invoke to BeginInvoke, then that will probably solve the 'race' problem.

Feedback