昨天一个朋友问我一个问题,需求是

            this.textBox1.Text = "睡眠前";
            Thread.Sleep(1000);
            this.textBox1.Text = "睡眠后";

  他想要的效果就是在显示的时候先显示第一个文本 然后睡眠一秒钟之后 显示第二文本,我们知道在单线程里面 在线程没有结束的时候是不可能显示出任何内容改变的,他的大部分内容还没有被cpu执行完毕,放在堆栈里面,这时候是不可能显示的,那既然提出来了 这边肯定想要解决掉 那只能启动多线程,让主线程先跑完 再让子线程去改 这样就可以解放窗体不能操作的问题了 但是 真的是这样吗

private void button1_Click(object sender, EventArgs e)
{
this.textBox1.Text = "睡眠前";

Task.Run(() => { Thread.Sleep(1000); this.textBox1.Text = "睡眠后"; });

}

 我们这样修改一下代码 理论上觉得 可以,但是运行发现 根本没反应,问题出现在哪呢 ,就是子线程修改不动主线程里面的东西,这样一来那我们是不是找到那个主线程 就行了呢

这里我们使用委托

        delegate void SetTextCallback(string text);
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.textBox1.Text = "睡眠前";          
          //  Task.Run(() => { Thread.Sleep(1000); this.textBox1.Text = "睡眠后"; });
           // SetTextCallback SetTextCallback;
          //  SetTextCallback = SetText;
            Task.Run(() => { SetText("睡眠后"); });
            


        }
        private void SetText(string text)
        {
            //子线程睡眠1秒
            Thread.Sleep(1000);
            if (this.textBox1.InvokeRequired)
            {
                SetTextCallback Callback = new SetTextCallback(SetText);
                this.Invoke(Callback, new object[] { text  });
            }
            else
            {
                this.textBox1.Text = text;
                this.textBox1.Refresh();
            }
        }

  这样 我们通过异步执行,让子线程通过textbook提供的InvokeRequired属性去判断 当前线程是否是在主线程内 不是的话就通过委托回调然到主线程里面去修改属性

 

以上是我个人理解 如果有什么不对的地方可以和我交流一下 

小白留

 posted on 2019-03-14 16:15  JetaimeBeaucoup  阅读(302)  评论(0编辑  收藏  举报