954,515 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

WMI Event Handlers unable to access GUI elements

My program talks to a USB device over a serial connection. I have WMI ManagementEventWatchers watching for the device to be plugged in and unplugged.

If I try to enable, disable, or change anything about the GUI from the event handlers for the WMI Events, I get a InvalidOperationException because a different thread owns the object.

How can I have an event handler (that apparently get called by a different thread) modify my GUI?

toadzky
Junior Poster in Training
96 posts since Mar 2007
Reputation Points: 10
Solved Threads: 0
 

You should probably try it with delegation!

http://msdn.microsoft.com/de-de/library/system.delegate.aspx

Good luck!

Wegginho
Newbie Poster
20 posts since Feb 2011
Reputation Points: 12
Solved Threads: 6
 

i'm not sure what you mean by 'it' or how delegates would be helpful. the issue is that the event is triggered in a thread that doesn't have access to my GUI.

toadzky
Junior Poster in Training
96 posts since Mar 2007
Reputation Points: 10
Solved Threads: 0
 

This is an extension method that will allow you to update controls on different threads:

private delegate void SetPropertyDelegate<TResult>(Control @this, Expression<Func<TResult>> property, TResult value);

public static void SetProperty<TResult>(this Control @this, Expression<Func<TResult>> property, TResult value) {
    var propertyInfo = (property.Body as MemberExpression).Member as PropertyInfo;

    if (propertyInfo == null ||
            !@this.GetType().IsSubclassOf(propertyInfo.ReflectedType) ||
            @this.GetType().GetProperty(propertyInfo.Name, propertyInfo.PropertyType) == null) {
        throw new ArgumentException("The lambda expression 'property' must reference a valid property on this Control.");
    }

    if (@this.InvokeRequired) {
        @this.Invoke(new SetPropertyDelegate<TResult>(SetProperty), new object[] { @this, property, value });
    } else {
        @this.GetType().InvokeMember(propertyInfo.Name, BindingFlags.SetProperty, null, @this, new object[] { value });
    }
}


You use it like this:

myTextBox.SetProperty(() => myTextBox.Text, "some string");
Momerath
Nearly a Senior Poster
3,386 posts since Aug 2010
Reputation Points: 1,232
Solved Threads: 558
 

I'll give it a try and let you know. Just out of curiosity, what's with all the @ characters?

toadzky
Junior Poster in Training
96 posts since Mar 2007
Reputation Points: 10
Solved Threads: 0
 
I'll give it a try and let you know. Just out of curiosity, what's with all the @ characters?

"... and the “@” character is allowed as a prefix to enable keywords to be used as identifiers."

Momerath
Nearly a Senior Poster
3,386 posts since Aug 2010
Reputation Points: 1,232
Solved Threads: 558
 

Since I'm using WPF instead of WinForms, the call for Invoke is done with:

this.Dispatcher.Invoke(/*insert delegate here*/);


Thanks for showing me the way to do it. Here's what I ended up with (since I didn't really need all the generic parts of your code, I simplified a bit):

private void delegate ControlModifier();
public void CreateControl()
{
   ctrl_Info.Content = new DeviceInfoPage();
}


Thanks for all your help!

toadzky
Junior Poster in Training
96 posts since Mar 2007
Reputation Points: 10
Solved Threads: 0
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: