日期:2014-05-20  浏览次数:20880 次

分享一個多線程委派的代碼
一般我們在實作多線程存取主線程控制項屬性時,必須以委派方式來存取,否則就有可能會出現 InvalidOperationException 例外,一般初學者總會犯這個錯誤,大都不知道需要委派的動作,總是在子線程用一行 textBox1.Text = "aaaaa" 就想改變控制項的屬性,卻換來 InvalidOperationException 的錯誤,而在一般情況下委派的動作總不會像 textBox1.Text = "aaaaa" 短短一行就這麼直覺的解決問題,總覺得委派代碼實在麻煩。如果你運作的環境是 .net framework 3.5(含以上),又覺得委派的代碼總是惹人厭的話,下面的代碼或許幫得上你解決惱人的委派問題,至少幫了我很多,分享給大家,以下是實例。

首先定義一個類別,來當然是 Control Class 擴充方法類別。
C# code

public static class ExtensionControl
{                                               
    public static object GetPropertySafe(this Control control, string propertyName)
    {
        object returnValue = null;
        Action func = () =>
        {
            Type type = control.GetType();
            returnValue = type.InvokeMember(propertyName, BindingFlags.GetProperty, null, control, null);
        };
        if (control.InvokeRequired)
        {
            control.Invoke(func);
        }
        else
        {
            func();
        }
        return returnValue;
    }

    public static object SetPropertySafe(this Control control, string propertyName, object value)
    {
        object returnValue = null;
        Action func = () =>
        {
            Type type = control.GetType();
            returnValue = type.InvokeMember(propertyName, BindingFlags.SetProperty, null, control, new object[] { value });
        };
        if (control.InvokeRequired)
        {
            control.Invoke(func);
        }
        else
        {
            func();
        }
        return returnValue;
    }

    public static object GetPropertySafe(this ToolStripMenuItem control, string propertyName)
    {
        object returnValue = null;
        Control owner = control.Owner;
        Action func = () =>
        {
            Type type = control.GetType();
            returnValue = type.InvokeMember(propertyName, BindingFlags.GetProperty, null, control, null);
        };
        if (owner.InvokeRequired)
        {
            owner.Invoke(func);
        }
        else
        {
            func();
        }
        return returnValue;
    }

    public static object SetPropertySafe(this ToolStripMenuItem control, string propertyName, object value)
    {
        object returnValue = null;
        Control owner = control.Owner;
        Action func = () =>
        {
            Type type = control.GetType();
            returnValue = type.InvokeMember(propertyName, BindingFlags.SetProperty, null, control, new object[] { value });                
        };
        if (owner.InvokeRequired)
        {
            owner.Invoke(func);
        }
        else
        {
            func();
        }
        return returnValue;
    }        

    public static object InvokeMethodSafe(this Control control, string methodName, params object[] args)
    {
        object returnValue = null;
        if (args == null)
        {
            args = new object[1];
            args[0] = null;
        }
        else if (args != null && args.Length == 0)
        {
            args = null;
        }
        Action func = () =>
        {
            Type type = control.GetType();                
            returnValue = type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, control, args);
        };
        if (control.InvokeRequired)
        {
            control.Invoke(func);
        }
        else
        {
            func();
        }
        return returnValue;
    }

    public static object InvokeMethodSafe(this ToolStripMenuItem control, string methodName, params object[] args)
    {
        object returnValue = null;
        if (args == null)
        {
            args = new object[1];
            args[0] = null;
        }
        else if (args != null && args.Length == 0)
        {
            args = null;
        }
        Control owner = control.Owner;
        Action func = () =>
        {
            Type type = control.GetType();
            returnValue = type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, control, args);
        };
        if (owner.InvokeRequired)
        {
            owner.Invoke(func);
        }
        else
        {
            func();
        }
        return returnValue;
    }
}