簡體   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