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?

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.

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");
commented: Very helpful. Gave me everything I needed to fix my problem. +5

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

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."

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!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.