一、System.Windows.Forms.MethodInvoker 类型是一个系统定义的委托,用于调用不带参数的方法。
private Thread myThread;

private void Form1_Load(object sender, EventArgs e)
{
myThread
= new Thread(new ThreadStart(RunsOnWorkerThread));
myThread.Start();
}

private void RunsOnWorkerThread()
{
MethodInvoker mi
= new MethodInvoker(SetControlsProp);
BeginInvoke(mi);
}

private void SetControlsProp()
{
label1.Text
= "myThread线程调用UI控件";
}


二、直接用System.EventHandle(可带参数)
 
private Thread myThread;

private void Form1_Load(object sender, EventArgs e)
{
myThread
= new Thread(new ThreadStart(RunsOnWorkerThread));
myThread.Start();
}

private void RunsOnWorkerThread()
{
//DoSomethingSlow();
string pList = "myThread线程调用UI控件";
label1.BeginInvoke(
new System.EventHandler(UpdateUI), pList);
}

//直接用System.EventHandler,没有必要自定义委托
private void UpdateUI(object o, System.EventArgs e)
{
//UI线程设置label1属性
label1.Text = o.ToString() + "成功!";
}
包装Control.Invoke
虽然第二个方法中的代码解决了这个问题。但它非常烦琐,如果辅助线程希望在结束的时候提供更多的反馈信息,而不是简单地给出
"Finieshed!"消息,则BeginInvoke过于复杂的使用方法会令人剩畏。为了传达其他消息,例如“正在处理”、“一切顺利”等等,
需要设法向UpdateUI函数传递一个参数。可能还需要添加一个进度栏以提高反馈能力。这么多次调用BeginInvoke可能导致辅助线程
受该代码支配,这样不仅会造成不便,而且考虑到辅助线程与UI的协调性,这样设计也不好。对这些分析之后,我们认为包装函数可
以解决这两个问题
 private Thread myThread;
        private void Form1_Load(object sender, EventArgs e)
        {
            myThread = new Thread(new ThreadStart(RunOnWorkerThread));
            myThread.Start();
        }
 
        private void RunOnWorkerThread()
        {
            for (int i = 0; i < 100; i++)
            {
                showProgress(Convert.ToString(i), i);
                Thread.Sleep(100);
            }
        }
 

        public void showProgress(string msg, int percentDone)
        {
            System.EventArgs e = new MyProgressEvents(msg, percentDone);
            object[] pList = { this, e };
            BeginInvoke(new MyProgressEventsHandler(UpdateUI), pList);
        }
 
        private delegate void MyProgressEventsHandler(object sender, MyProgressEvents e);
        private void UpdateUI(object sender, MyProgressEvents e)
        {
            lblStatus.Text = e.Msg;
            myProgressControl.Value = e.PercentDone;
        }
 
        public class MyProgressEvents : EventArgs
        {
            public string Msg;
            public int PercentDone;
 
            public MyProgressEvents(string msg, int per)
            {
                Msg = msg;
                PercentDone = per;
            }
        }
ShowProgress方法对将调用引向正确线程的工作进行封装。这意味着辅助线程代码不用担心需要过多的关注UI细节,而只要定期调用
ShowProgress即可
如果我提供一个设计为可从任何线程调用的公共方法,则完全有可能某人会从UI线程调用这个方法。在这种情况下,没必要调用
BeginInvoke,因为我已经处于正确的线程中。调用Invoke完全是浪费时间和资源,不如直接调用适当的方法。为了避免这个情况,
Control类将公开一个称为InvokeRequired的属性,这是“只限UI线程”规则的另一个例外。它可从任何线程读取,如果调用线程是
UI线程,则返回假,其他线程则返回真。这以为着:我可以按以下方式修改包装
 public void ShowProgress(string msg, int percentDone)
        {
            if (InvokeRequired)
            {

                //as before
                //..
            }
            else
            {
                //we're already on the UI thread just
                //call straight through
                UpdateUI(this, new MyProgressEventsHandler(msg, percentDone));
            }
        }





三、演示程序
        线程中调用部分:
结束。
//初始化参数列表
List<String> paramList = new List<string>();
paramList.Add(
"0");
paramList.Add(
"");

//这里采用系统委托的方式,实现线程内操作系统界面控件。
paramList[0] = "0"; paramList[1] = "清除屏幕信息";
lstBoxCatchData.BeginInvoke(
new System.EventHandler(UpdateListBox),
paramList);
/// <summary>
/// 提供给系统委托事件调用,解决线程内操作界面控件的目的
/// </summary>
/// <param name="obj"></param>
/// <param name="e"></param>
private void UpdateListBox(object obj,System.EventArgs e)
{
//强制类型转换
List<String> paramList = (List<string>)obj;
if (paramList[0] == "0")
{
this.lstBoxCatchData.Items.Clear();
}
else if (paramList[0] == "1")
{
this.lstBoxCatchData.Items.Add(paramList[1].ToString());
}
}