首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

分享一個多線程委派的代碼解决思路

2012-02-01 
分享一個多線程委派的代碼一般我們在實作多線程存取主線程控制項屬性時,必須以委派方式來存取,否則就有可

分享一個多線程委派的代碼
一般我們在實作多線程存取主線程控制項屬性時,必須以委派方式來存取,否則就有可能會出現 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;    }}     


類別中分別定義 SetPropertySafe, GetPropertySafe, InvokeMethodSafe 方法,當作是 Control 的擴充方法,在一個 WindowsFormsApplication 加入該代碼或者自己做成 dll 引用都可以,以下是多線程實作委派的示例。
C# code
namespace WindowsFormsApplication1{    public partial class MainForm : Form    {                public MainForm()        {            InitializeComponent();        }        private void button1_Click(object sender, EventArgs e)        {            Thread thread = new Thread(                ThreadStart =>                {                    //this.textBox1.Text = "Thread Edit";                    //將上方會產生 InvalidOperationException 的代碼註解,改以下方代碼                                        this.textBox1.SetPropertySafe("Text", "ThreadEdit");                }            );            thread.IsBackground = true;            thread.Start();        }    }}

這樣就徹底解決多線程存取主線程控制項委派的麻煩代碼,同樣一行程式碼做相同的事,接著就可以舉一反三再擴充 Control 方法,技術上並沒有多深,只是一個比較方便的代碼,希望能夠讓一些人在實作多線程委派時,能夠少走彎路,一同為程式加油。


[解决办法]
这个得学习一下
[解决办法]
不错,谢谢分享,自己写扩展方法是个好办法,学习了
[解决办法]
慢慢来研究,不能让他沉了!
[解决办法]
学习中。
[解决办法]
支持原创,谢谢分享!

热点排行