繁体   English   中英

WPF Window 移动鼠标时滞后

[英]WPF Window lag when moving mouse

任何人都可以阐明为什么 WPF window 在您将鼠标快速移动到它上面时会滞后吗? 有没有办法解决? 也许更改 window 渲染设置?

以下代码运行矩形的平滑 animation,直到您开始将鼠标移到 window 上,帧率将急剧下降(使用 VS 中的应用程序分析器确认)。 也发生在没有调试器的发布版本中。

我读过当我 hover 超过我的应用程序 Window 时,为什么 WPF 中的调度程序计时器滞后? 这建议使用不同的计时器来更新基础数据。 我尝试了 System.Threading.Timer、System.Timers.Timer 和 System.Windows.Threading.DispatcherTimer,同时创建了一个新线程以使用 Thread.Sleep 更新循环中的值。 所有这些都提供相同的结果,所以我认为它实际上与计时器本身没有任何关系。

代码隐藏:

    public partial class MainWindow : Window, INotifyPropertyChanged
{
    private int _value;
    public int Value { get => _value; set { _value = value; RaisePropertyChangedEvent(); } }
    public event PropertyChangedEventHandler PropertyChanged;
    public Timer Timer { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;

        Timer = new Timer((o) =>
        {
            Value = Value > 100 ? -100 : Value + 1;
        }, null, 0, 10);
    }

    protected void RaisePropertyChangedEvent([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

XAML:

<Window x:Class="MouseLagTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:MouseLagTest"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Grid>
    <Rectangle Width="50" Height="50" Fill="Red">
        <Rectangle.RenderTransform>
            <TranslateTransform X="{Binding Value}"/>
        </Rectangle.RenderTransform>
    </Rectangle>
</Grid>

编辑此问题似乎是在针对 .Net Framework 4.X 和 .Net Core 构建时发生的。 如果使用 Framework 3.X 构建,无论鼠标移动如何,它都运行得非常流畅。 我更喜欢使用 3.X 的解决方案不是一个选项。

因此,当您从后台线程调用 PropertyChanged 时,WPF 绑定会自动将更新编组到 GUI 线程以进行更新。

WPF 数据绑定线程安全?

出于某种原因,我认为这是快速移动鼠标时出现延迟的地方,可能是由于 Dispatcher 队列中的事件优先级。

如果您手动将更新编组到 GUI 线程,它可以解决问题。

即对于特定的属性更新:

Timer = new Timer((o) =>
{
    Application.Current.Dispatcher.BeginInvoke(new Action(() =>
    {
        Value = Increment(Value);
    }));
}, null, 0, 10);

或者一般来说:

protected void RaisePropertyChangedEvent(String propertyName = "")
{
    Application.Current.Dispatcher.BeginInvoke(new Action(() =>
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }));
}

无论鼠标移动如何,执行上述任一操作都会提供平滑的更新。 如果使用计时器,您也可以只使用 DispatcherTimer,以便在主线程的 Dispatcher 循环顶部执行调用。 https://learn.microsoft.com/en-us/do.net/api/system.windows.threading.dispatchertimer?view=windowsdesktop-5.0

如果有更好的方法来实现这一点,或涉及任何警告,很高兴听到一些建议。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM