C# 当移动一个简单的矩形时,wpf中有3种不同结果的模拟方法

C# 当移动一个简单的矩形时,wpf中有3种不同结果的模拟方法,c#,wpf,C#,Wpf,我对wpf应用程序中的任务有一个奇怪的问题。我创建了一个简单的程序,并在其上放置了一个名为“RectObj”的矩形,该矩形带有一个调用3种方法之一的按钮。我正试图用C#代码在屏幕上平滑地滑动它。我不想使用动画,我真的想知道为什么下面的代码在每种情况下都会这样做,以及如何在没有动画的情况下修复它 // has a delay in the initial few moments without moving, then jumps to it's position and thereafter r

我对wpf应用程序中的任务有一个奇怪的问题。我创建了一个简单的程序,并在其上放置了一个名为“RectObj”的矩形,该矩形带有一个调用3种方法之一的按钮。我正试图用C#代码在屏幕上平滑地滑动它。我不想使用动画,我真的想知道为什么下面的代码在每种情况下都会这样做,以及如何在没有动画的情况下修复它

// has a delay in the initial few moments without moving, then jumps to it's position and thereafter runs perfectly smooth even after another button press
    public void test()
    {
        Task.Run(() =>
        {
            for (int x = 0; x < 100; x++)
            {
                this.Dispatcher.Invoke((() =>
                {
                    var margin = RectObj.Margin;
                    margin.Left = testValue++;
                    RectObj.Margin = margin;
                }));
                Thread.Sleep(10);
            }
        });
    }
    // runs, but jagged movements/refreshing
    public void test2()
    {
        Task.Run(() =>
        {
            for (int x = 0; x < 100; x++)
            {
                this.Dispatcher.Invoke((() =>
                {
                    var margin = RectObj.Margin;
                    margin.Left = testValue++;
                    RectObj.Margin = margin;
                    Thread.Sleep(10);
                }));
            }
        });
    }
    // does not update display until task is completed
    public void test3()
    {
        Task.Run(() =>
        {
            this.Dispatcher.Invoke((() =>
            {
                for (int x = 0; x < 100; x++)
                {
                    var margin = RectObj.Margin;
                    margin.Left = testValue++;
                    RectObj.Margin = margin;
                    Thread.Sleep(10);
                }
            }));
        });
    }
//在最初的几分钟内有一个延迟,但没有移动,然后跳到它的位置,然后即使再按一次按钮,运行也非常平稳
公开无效测试()
{
Task.Run(()=>
{
对于(int x=0;x<100;x++)
{
this.Dispatcher.Invoke((()=>
{
var保证金=矩形保证金;
margin.Left=testValue++;
矩形边缘=边缘;
}));
睡眠(10);
}
});
}
//跑步,但动作参差不齐/令人耳目一新
公共无效测试2()
{
Task.Run(()=>
{
对于(int x=0;x<100;x++)
{
this.Dispatcher.Invoke((()=>
{
var保证金=矩形保证金;
margin.Left=testValue++;
矩形边缘=边缘;
睡眠(10);
}));
}
});
}
//在任务完成之前不更新显示
公共无效测试3()
{
Task.Run(()=>
{
this.Dispatcher.Invoke((()=>
{
对于(int x=0;x<100;x++)
{
var保证金=矩形保证金;
margin.Left=testValue++;
矩形边缘=边缘;
睡眠(10);
}
}));
});
}

第一种情况,我真的不知道你为什么第一次耽搁。我猜它正在进行某种初始化(否则每次按下按钮都会有延迟),但我不确定具体是什么

对于案例二和案例三,您必须了解两件事:

  • Dispatcher.Invoke中的任何内容都将由UI线程执行
  • 当调度程序回调正在运行时,UI不会刷新。长话短说,UI线程执行一个无限循环,在刷新UI(即,根据控件的值绘制屏幕上应该显示的内容)和执行与调度程序一起排队的任何回调之间交替进行
从这里,很容易理解发生了什么:

  • 在第二种情况下,UI线程执行
    线程.Sleep
    。当它处于睡眠状态时,它无法刷新UI
  • 在第三种情况下,您永远不会退出dispatcher,UI线程没有机会重新绘制屏幕

至于知道如何修复它。。。当然,最好的方法是使用动画。如果您确实不想,至少使用
TranslateTransform
移动控件,而不是更改边距。使用
TranslateTransform
(指定给控件的
RenderTransform
属性)只会更改控件的视觉外观(而不是实际位置),因此速度很快。更改边距会迫使WPF重新计算部分布局,这需要CPU。

嘿,谢谢。现在对案例2和3有意义了。我现在了解了调度器的工作原理。而translateTransform似乎解决了初始滞后的问题。谢谢你的帮助