C#Thread.Sleep()_在PC之间执行的其他时间
我有个问题 下面的来源是当按下按钮时将面板向左和向右移动的线程 但是,如果在开发PC上移动约1秒,则在测试PC上大约需要4秒 *测试PC的硬件性能更好 我想知道为什么会出现这些结果C#Thread.Sleep()_在PC之间执行的其他时间,c#,multithreading,winforms,runtime,sleep,C#,Multithreading,Winforms,Runtime,Sleep,我有个问题 下面的来源是当按下按钮时将面板向左和向右移动的线程 但是,如果在开发PC上移动约1秒,则在测试PC上大约需要4秒 *测试PC的硬件性能更好 我想知道为什么会出现这些结果 private void move() { while (Moving) { SlidePanel.BeginInvoke(new Action(() => { if (SlideDirec
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);
}
}
private void move()
{
(移动中)
{
SlidePanel.BeginInvoke(新操作(()=>
{
if(SlideDirection==0)//左
{
左滑动面板-=4;
如果(滑动面板左)
{
SystemPanel.BringToFront();
}));
移动=假;
}
}
否则//
{
左滑动面板+=4;
如果(SlidePanel.Left>=EnvSettingbtn.Left)
{
SlidePanel.Left=环境设置btn.Left;
EnvironmentPanel.BeginInvoke(新操作(()=>
{
EnvironmnetPanel.BringToFront();
}));
移动=假;
}
}
}));
睡眠(1);
}
}
- 使用[等待任务与Daly(1)] 我已经确认两个环境的运行时间相同。 在一个更好的环境中,Thread.sleep(1)的速度变慢了,这感觉很奇怪
- 这不是线程安全的。您需要以某种方式同步移动
。最简单的方法是使用lock
有更有效的方法,但从这里开始学习是你最安全的选择。像这样的东西很管用
private readonly object movingLock = new object();
private bool _moving;
private bool Moving
{
get { lock (movingLock) return _moving }
set { lock (movingLock) _moving = value; }
}
关于为什么需要这样做的一个重要说明<代码>如果不同步(\u moving)
可以返回旧值
您可以在此处使用volatile
,但与流行观点相反,它仍然不能保证读取最新的值
您将看到由于
线程睡眠(1)
而产生的差异。由内核来处理线程调度。它不能保证时间
我也不明白为什么你已经在UI线程上了,却在做
BeginInvoke
。您可以使用Control.invokererequired
进行检查
如果您已经在UI线程上,而BeginInvoke
,会发生什么情况
它不会立即执行。它被放置在消息队列中。队列的大小也会增加显著的差异
绘制消息在队列中的优先级较低。如果要处理的消息会改变油漆,为什么还要麻烦油漆呢?因此,这也会延迟绘制。您可以发布
移动的声明吗?@Zer0我将布尔值声明出线程。[bool Moving=false]当按钮事件发生时,更改Moving=true->thread start您能提供一个权威的来源吗?为什么volatile不能解决这个问题?无论哪种方式,我都读过一些意见,但没有看到一个好的关于问题细节的来源。@JonasH volatile真正要做的是告诉编译器“不要优化它”,因为许多编译器优化包括读写重新排序。这是一个深入的例子。我不会称任何来源为“权威”,包括我自己。提供的you链接说,如果架构需要,访问易失性字段将发出围栏。围栏应足以确保价值是最新的。也就是说,围栏同时影响编译器和cpu。所以我仍然不明白为什么volatile是不够的。我建议读整页。引用:“…文档说明使用volatile关键字可以确保字段中始终存在最新的值。这是不正确的…”Joe Duffy编写了示例代码(他在Microsoft工作,写了一本关于并发性的书,是TPL的负责人).对于那些想要像volatile
这样易于使用而又没有陷阱的人,只需使用(和VolatileWrite
)即可。