您的位置:首页 > 编程语言 > C#

C# 中MethodInvoker的理解

2015-07-09 20:28 549 查看

以下引用自: c#使用MethodInvoker解决跨线程访问控件

net 原则上禁止跨线程访问控件,因为这样可能造成错误的发生,有一种方法是禁止编译器对跨线程访问作检查,Control.CheckForIllegalCrossThreadCalls = false;可以实现访问,但是出不出错不敢保证C#跨线程访问控件运行时错误。

使用MethodInvoker即可解决

看看系统定义, 与event 的区别

public delegate void MethodInvoker();

public delegate void EventHandler(object sender, EventArgs e);

简单来说 :

MethodInvoker 是不带参数的委托。

EventHandler 是可带参数的委托

我是这样理解的, 开启新线程 threadRun, 在新线程中使用MethodInvoker 委托执行 run()方法, 这个时候 run() 方法其实是在主线程中执行的, 这样就避免了 跨线程访问控件, 以下是我的测试代码:

private void button1_Click(object sender, EventArgs e)
        {
            Thread.CurrentThread.Name = "MainThread";       //主线程命名为 MainThread
            Thread td = new Thread(threadRun);
            td.Name = "ChildThread";                        //子线程命名为 ChildThread
            td.Start();
        }

        private void ChangeText()
        {
            this.textBox1.Text = Thread.CurrentThread.Name; //TextBox1内容被修改的线程的名字
        }

        private void threadRun()
        {
            MessageBox.Show(Thread.CurrentThread.Name);     //弹出对话框, 当前运行线程的名字
            MethodInvoker In = new MethodInvoker(ChangeText);
            this.BeginInvoke(In);


运行后, 点击 Button 首先弹出对话框 ChildThread, 然后 TextBox1 改为 MainThread

然后我的牛角劲又来了, ChangeText 被 MethodInvoker 插入到主线程中运行, 那么 ChangeText 应该是在 button1_Click 完全结束后才运行吧, 测试代码

private void button1_Click(object sender, EventArgs e)
        {
            Thread.CurrentThread.Name = "MainThread";       //主线程命名为 MainThread
            Thread td = new Thread(threadRun);
            td.Name = "ChildThread";                        //子线程命名为 ChildThread
            td.Start();

            int k=0;                                        //让主线程全速运行一段时间
            for (long i = 0; i < 1000000000; i++)
            {
                if (k > 10000) k = 0;
                k = k+5;
            }
            MessageBox.Show("MainThread全速运算刚刚结束了");
        }

        private void ChangeText()
        {
            MessageBox.Show(Thread.CurrentThread.Name);     //弹出执行ChangeText的线程的名字
        }

        private void threadRun()
        {
            MessageBox.Show(Thread.CurrentThread.Name);     //弹出对话框, 当前运行线程的名字
            MethodInvoker In = new MethodInvoker(ChangeText);
            this.BeginInvoke(In);
        }


可惜并不是我想的那样, 运行情况是先弹出 ChildThread, 然后弹出 MainThread, 最后才弹出 MainThread全速运算刚刚结束了

有谁可以解释一下么???????????? 难道同一个线程也有CPU时间片的概念? 以前听说过线程插入进程, 但没听说过 线程也可以被插入啊?


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: