c# - C# Thread.Sleep() _PC 之间执行的其他时间
问题描述
我有个问题。
下面的源码是按下按钮时将面板向左和向右移动的线程。
但是,如果在开发 PC 上移动大约 1 秒,则在测试 PC 上大约需要 4 秒。
*测试 PC 的硬件性能更好。
我想知道为什么会出现这些结果。
private void move()
{
while (Moving)
{
SlidePanel.BeginInvoke(new Action(() =>
{
if (SlideDirection == 0) // Left
{
SlidePanel.Left -= 4;
if (SlidePanel.Left <= SystemSettingbtn.Left)
{
SlidePanel.Left = SystemSettingbtn.Left;
SystemPanel.BeginInvoke(new Action(() =>
{
SystemPanel.BringToFront();
}));
Moving = false;
}
}
else // Right
{
SlidePanel.Left += 4;
if (SlidePanel.Left >= EnvSettingbtn.Left)
{
SlidePanel.Left = EnvSettingbtn.Left;
EnvironmnetPanel.BeginInvoke(new Action(() =>
{
EnvironmnetPanel.BringToFront();
}));
Moving = false;
}
}
}));
Thread.Sleep(1);
}
}
- 使用 [ await Task.With Daly (1) ] 我已经确认两个环境具有相同的运行时间。感觉很奇怪 Thread.sleep(1) 在更好的环境中变慢了。
解决方案
这不是线程安全的。你需要以Moving
某种方式同步。最简单的方法是使用lock
.
有更有效的方法,但从这里开始学习是您最安全的选择。像这样的东西有效。
private readonly object movingLock = new object();
private bool _moving;
private bool Moving
{
get { lock (movingLock) return _moving }
set { lock (movingLock) _moving = value; }
}
关于为什么需要这样做的一个重要说明。 if (_moving)
没有同步可以返回旧值。
您可以volatile
在此处使用,但与流行的观点相反,它仍然不能保证读取最新值。
您将看到由于Thread.Sleep(1)
. 由内核来处理线程调度。它不保证那个时间。
我也不明白为什么你BeginInvoke
已经在 UI 线程上。你可以Control.InvokeRequired
用来检查。
如果你BeginInvoke
已经在 UI 线程上会发生什么?
它不会立即执行。它被放置在消息队列中。该队列的大小也会增加显着的差异。
绘制消息在队列中的优先级较低。如果有要处理的消息会改变绘画,为什么还要费心绘画呢?所以这也耽误了绘画。
推荐阅读
- compiler-construction - llvm IR 中的冗余基本块
- json - jasper 中的交叉表仅显示输入 json 中的第一列
- javascript - 参照父对象展平嵌套对象
- android - 任务':app:transformClassesWithDesugarForRelease'的离子执行失败
- c++ - 模板类的工厂方法
- android - 房间数据库和 Glide 插件之间的 Gradle 多模块 annotationProcessor 编译问题
- javascript - 如何将字符串转换为 HTML 标签
- angular - 将表单值修改为用户类型
- java - Java 8 - 基于特定顺序的自定义排序
- python - count numpy 二维数组计数