昨天一个朋友问我一个问题,需求是
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属性去判断 当前线程是否是在主线程内 不是的话就通过委托回调然到主线程里面去修改属性
以上是我个人理解 如果有什么不对的地方可以和我交流一下
小白留