[求解]关于Thread.Sleep()引起的消息处理问题?

SSClearn27 2017-07-27 12:48:02
本人真正的小白,但渴望学习,这一个月一直在看C#的书,现在手头在看的是C#图解教程第4版,在看到异步编程的GUI的P416-P418的例子时,对书中的一个问题感到十分困惑,查了两天了,都没解决。求大神们救救我这个希望学习的小白了,脑子被这里搞混了,瞬间学习不下去了。问题是这样的,贴上窗口初始状态图片和代码。


private void btnDoStuff_Click(object sender,RoutedEventArgs e) // btnDoStuff是按钮的名字
{
btnDoStuff.IsEnabled = false;
lblStatus.Content = "Doing Stuff"; //lblStatus是标签的名字
//希望实现的是点击按钮后,按钮变成禁用状态,同时将文本标签的内容改为“Doing Stuff”

Thread.Sleep(4000);

lblStatus.Content = "Not Doing Anything";
btnDoStuff.IsEnabled = true;
//休眠4S后,按钮恢复可用状态,同时将文本标签内容改为“Not Doing Anything"。
}

实际执行后点击按钮后,
1:卡死4秒,
2:然后标签马上变成了"Not Doing Anything",按钮是可用状态。
问题是为什么不会是
1:”标签内容先变成Doing Stuff,按钮状态变为禁用”,
2:然后再卡死4秒,
3:标签变成了"Not Doing Anything",按钮变回可用状态。

书上解释了消息的处理,有句原话是:“但在处理程序本身退出(即休眠4S并退出)之前,这些消息都无法执行。然后所有的行为都发生了,但速度太快肉眼根本看不见。”
书上的意思是对于实际情况,是先休眠了4S?然后再一下子执行了”标签内容先变成Doing Stuff,按钮状态变为禁用”,标签再变成"Not Doing Anything",按钮变回可用状态?
这个执行顺序是什么原因啊?

很僵硬啊,对这个消息处理瞬间懵逼,书上把Thread.Sleep(4000)改成了await Task.Delay(4000)语句来解决这个问题。
...全文
405 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
橘子皮... 2017-07-27
  • 打赏
  • 举报
回复
btnDoStuff.IsEnabled = false; lblStatus.Content = "Doing Stuff"; 的确发生了,不过你看不到,因为你的sleep在主线程里,这样就堵塞了主线程,UI显示的结果没法看到,sleep应该用单独的线程来搞,或者干脆加doevents,但是这个方法貌似不怎么好
SSClearn27 2017-07-27
  • 打赏
  • 举报
回复
引用 3楼ilikeff8 的回复:
国内很多这种书就是喜欢吧简单事情说复杂了, 就是因为你事情都在主线程做,sleep阻塞了UI主线程,导致界面没办法刷新
谢谢谢谢,真的很感谢
SSClearn27 2017-07-27
  • 打赏
  • 举报
回复
引用 1楼橘子皮zzz 的回复:
btnDoStuff.IsEnabled = false; lblStatus.Content = "Doing Stuff"; 的确发生了,不过你看不到,因为你的sleep在主线程里,这样就堵塞了主线程,UI显示的结果没法看到,sleep应该用单独的线程来搞,或者干脆加doevents,但是这个方法貌似不怎么好
嗯嗯嗯嗯,有点点开了脑子里的那种阻塞,,真的谢谢
SSClearn27 2017-07-27
  • 打赏
  • 举报
回复
引用 2楼娃都会打酱油了 的回复:
你在Sleep之前缺少一句Application.DoEvents()来告知界面强制重绘 正常Frame是要等你整个代码跑完了才会重绘界面
啊啊啊啊啊,懂了懂了,谢谢谢谢,真的非常感谢!
橘子皮... 2017-07-27
  • 打赏
  • 举报
回复
还有你那个什么await task,delay是什么鬼,怎么我输入进去不能用? vb里应该这么写吧 Dim a As task = New Task(Sub() Thread.Sleep(1000)) a.Start() a.Wait()
SSClearn27 2017-07-27
  • 打赏
  • 举报
回复
第一次用CSDN,不知道咋逐条回复么,但是突然看到三条针对的消息,而且让我明白了,真的很想逐条感谢一下!太感谢啦
ilikeff8 2017-07-27
  • 打赏
  • 举报
回复
国内很多这种书就是喜欢吧简单事情说复杂了, 就是因为你事情都在主线程做,sleep阻塞了UI主线程,导致界面没办法刷新
  • 打赏
  • 举报
回复
你在Sleep之前缺少一句Application.DoEvents()来告知界面强制重绘 正常Frame是要等你整个代码跑完了才会重绘界面

111,093

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧