Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#Thread.Sleep()_在PC之间执行的其他时间_C#_Multithreading_Winforms_Runtime_Sleep - Fatal编程技术网

C#Thread.Sleep()_在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

我有个问题

下面的来源是当按下按钮时将面板向左和向右移动的线程

但是,如果在开发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);
        }
    }
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
      )即可。