使用繁忙的UI线程拖动WPF Slider滑块会导致意外值

时间:2012-06-13 17:27:41

标签: wpf multithreading slider

编辑:在Slider.ValueChanged事件中长时间锁定。删除它可以阻止这种怪异。不好的做法,但这种行为对我来说仍然没有意义。它可能与消息队列有关,但如果可能的话,我想要一个解释。

当UI线程*上有重要工作时,WPF Slider不会按预期与鼠标交互。如果我沿一个方向拖动拇指,拇指通常会在鼠标光标前面前进,然后返回。该运动应该只导致增加ValueChanged事件,但事件有时会减少。有时这种振荡也发生在鼠标光标后面。似乎鼠标的位置是通过当前的速度来预测的。

我可以改变这种行为,还是我做错了什么?

切换IsSnapToTickEnabled无济于事。

*将大型BitmapSource分配给图像。 BitmapSource是在工作线程中创建的。

<Window x:Class="WPFSliderBug.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Image Name="image1" Stretch="Fill" />
    <Slider HorizontalAlignment="Right" Name="slider1" VerticalAlignment="Stretch" Orientation="Vertical" />
</Grid>
</Window>

xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Imaging;

using System.Threading;

namespace WPFSliderBug
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private volatile bool m_run = true;
        private double m_sliderValue;

        public MainWindow()
        {
            InitializeComponent();

            this.Closing += new System.ComponentModel.CancelEventHandler(MainWindow_Closing);
            this.slider1.Minimum = 1;
            this.slider1.Maximum = 30;
            this.slider1.SmallChange = 0.5;
            this.slider1.LargeChange = 0.5;
            this.slider1.TickFrequency = 0.5;
            this.slider1.TickPlacement = System.Windows.Controls.Primitives.TickPlacement.Both;
            this.slider1.ValueChanged += new RoutedPropertyChangedEventHandler<double>(slider1_ValueChanged);

            Thread t = new Thread((unused_state) =>
            {
                while (m_run)
                {

                    BitmapSource bmp;
                    lock (this)
                    {
                        bmp = ToBitmapSource();
                        bmp.Freeze();
                    }

                    this.Dispatcher.Invoke(new Action(delegate()
                    {
                        image1.Source = bmp;
                    }));
                }
            });

            t.Start();
        }

        void slider1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            lock (this)
            {
                m_sliderValue = e.NewValue;
            }
        }

        void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {

                m_run = false;
        }

        public BitmapSource ToBitmapSource()
        {
            Random rng = new Random();
            double dpi = 96;
            int bytesPerPixel = 1;
            int width = 2048;
            int height = 2048;

            int stride = ((width * 32 + 31) & ~31) / 8;

            UInt32[] pixelData = new UInt32[width * height];
            for (int i = 0; i < pixelData.Length; ++i)
            {
                double r = rng.NextDouble();
                r = Math.Sin(r) * Math.Cos(r) + Math.Asin(r);
                pixelData[i] = (uint)(r * UInt32.MaxValue);
            }


            BitmapSource bmpSource = BitmapSource.Create(width, height, dpi, dpi,
                PixelFormats.Bgr32, null, pixelData, stride);

            return bmpSource;
        }
    }
}

0 个答案:

没有答案