Click here to Skip to main content
Click here to Skip to main content

Component Manipulator from separate threads

, 26 Aug 2009
Rate this:
Please Sign up or sign in to vote.
An easy to use form component manipulator from separate threads.

Introduction

When using multiple threads in C# and you want to modify a control on the form, you receive an error like this:

Cross-thread operation not valid: Control 'XXX' accessed from 
       a thread other than the thread it was created on.

To resolve this problem, you have to create a delegate for each component you want to modify, or, if you want to separately modify more properties, more delegates. If you want to modify many components, you end up creating a lot of delegates and delegate methods.

Background

Creating a simple delegate

Declaring the delegate:

private delegate void updateFileLabel(string str, int index);

Declaring the method:

private void updateLabel(string str, int index)
{
    if (label3.InvokeRequired)
    {
        updateFileLabel d = new updateFileLabel(updateLabel);
        this.Invoke(d, new object[] { str, index });
    }
    else
    {
        label3.Text = "Proccessing: " + 
          str.Substring(0, Math.Min(5,str.LastIndexOf("\\"))) + 
          "..." + str.Substring(str.LastIndexOf("\\"));
    }
}

And if you want to manipulate many components and more than one property, there is a lot of code to write. The solution: Component Manipulator. To access the different properties, the class uses GetType() that is defined for any object, and from there, using Reflection, everything is simple.

Using the code

The use of the code is simple. All the methods are static. There are three different methods to manipulate the components.

GetComponentProperty

public static object GetComponentProperty(Control component, string query)
{
    if (component == null) { return null; }
    if (component.InvokeRequired)
    {
        GetComponentPropertyDelegate delegateObject = 
            new GetComponentPropertyDelegate(GetComponentProperty);
        return component.Invoke(delegateObject, new object[] { component, query });
    }
    else
    {
        object obj = GetQueryObject(component, ref query);
        Property property = GetProperty(query);
        obj = GetObjectPropertyValue(obj, property.name);
        if (obj == null) { return null; }
        if (property.index != null)
        {
            obj = GetItemFromArray(obj, property.index);
        }
        return obj;
    }
}

This method uses a delegate:

protected delegate object GetComponentPropertyDelegate(Control component, string query);

To use this method, you write:

bool isChecked = (bool)ComponentManipulator.GetComponentProperty(listView1, 
                      "Items[" + item + "].Checked");
string fileName = ComponentManipulator.GetComponentProperty(listView1, 
                      "Items[" + item + "].Text") as string;

The query parameter is used to access the property you want.

SetComponentProperty

public static void SetComponentProperty(Control component, string query, object value)
{
    if (component == null || value == null) { return; }
    if (component.InvokeRequired)
    {
        SetComponentPropertyDelegate delegateObject = 
                    new SetComponentPropertyDelegate(SetComponentProperty);
        component.Invoke(delegateObject, new object[] { component, query, value });
    }
    else
    {
        object obj = GetQueryObject(component, ref query);
        Property property = GetProperty(query);
        if (property.index != null)
        {
            obj = GetObjectPropertyValue(obj, property.name);
            if (obj == null) { return; }
            SetItemFromArray(obj, property.index, value);
        }
        else
        {
            SetObjectPropertyValue(obj, query, value);
        }
    }
}

This method uses a delegate:

protected delegate void SetComponentPropertyDelegate(Control component, 
                        string query, object value);

To use this method, you write:

ComponentManipulator.SetComponentProperty(listView1, 
   "Items[" + item + "].SubItems[1].Text", 
   "Not selected for encoding");

The query parameter is used to access the property you want. The value parameter is the value to set for the property you access with the query.

CallComponentMethod

public static void CallComponentMethod(Control component, string query, object [] parameters)
{
    if (component == null) { return; }
    if (component.InvokeRequired)
    {
        CallComponentMethodDelegate delegateObject = 
                  new CallComponentMethodDelegate(CallComponentMethod);
        component.Invoke(delegateObject, new object[] { component, query });
    }
    else
    {
        object obj = GetQueryObject(component, ref query);
        Property property = GetProperty(query);
        if (property.index == null)
        {
            CallObjectMethod(obj, query, parameters);
        }
    }
}

This method uses a delegate:

protected delegate void CallComponentMethodDelegate(Control component, 
                                  string query, object [] parameters);

To use this method, you write:

ComponentManipulator.CallComponentMethod(listView1, 
         "Items[" + item + "].SubItems[1].ResetStyle");

Note: The method must not have parentheses ().

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

badicuady
Software Developer Ipsos Group
Romania Romania
No Biography provided
Follow on   Google+

Comments and Discussions

 
GeneralOvercomplicated solution PinmemberGeorgeTheElder26-Aug-09 17:34 
AnswerRe: Overcomplicated solution Pinmemberbadicuady27-Aug-09 4:43 
GeneralRe: Overcomplicated solution PinmemberTobiasP10-Sep-09 4:07 
GeneralVery good :) PinmemberAnt210026-Aug-09 3:19 
GeneralRe: Very good :) Pinmemberdequadin26-Aug-09 4:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 26 Aug 2009
Article Copyright 2009 by badicuady
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid