יום חמישי, 21 באוקטובר 2010

WPF Blinking Performance problem

Dooring our development I came a cross an interesting problem regarding performance with wpf story board. I developed an application that has some blinking/flashing user controls , I implemented that behavior with a binding to a property that starts a story board which tells the control's background color to go form whit to red. you can see in the example how to flashing is implemented.

    <DataTrigger Value="True" Binding="{Binding FlashMe, Mode=OneWay}" >
                    <DataTrigger.EnterActions>
                        <BeginStoryboard  x:Name="beginirrgular" >
                            <BeginStoryboard.Storyboard>
                                <Storyboard >
                                    <ColorAnimation Storyboard.TargetProperty="Background.Color" FillBehavior="Stop" RepeatBehavior="Forever"  From="Red" To="White" Duration="0:0:1" />
                                </Storyboard>
                            </BeginStoryboard.Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                    <DataTrigger.ExitActions >
                        <StopStoryboard  BeginStoryboardName="beginirrgular"/>
                    </DataTrigger.ExitActions>
                </DataTrigger>
            </Style.Triggers>
   
When I ran the application I saw that the CPU usage is around 20 in the task manager ,I believe that this causes a major performance problem.

To solve this problem I tried some several different ways the one that worked is what I will show in this post.

I used a converter and a timer thread that changes a boolean property to change the background color, the effect GUI wise is the same and performance wise the CPU usage was much lower than before.

This is the Code:
bool _myflash = false;
        System.Timers.Timer _mytimer;

        public bool Myflash
        {
            get { return _myflash; }
            set 
            {
                _myflash = value;
                OnPropertyChanged(new PropertyChangedEventArgs("Myflash"));
            }
        }

        public MainWindow()
        {            
            _mytimer = new System.Timers.Timer(500);
            _mytimer.Elapsed += new System.Timers.ElapsedEventHandler(_mytimer_Elapsed);
            this.DataContext = this;
            InitializeComponent();
        }

        void foo()
        {            
            Myflash = !Myflash;
        }

        void _mytimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            Action method = foo;
            dis.BeginInvoke(method);
        }
As you can see there is a timer that fries the elapsed event and changes the bool MyFlash using dispatcher.

This is the converter that switches the color back and forth,

public class ConvertMe : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value != null)
            {
                bool val = System.Convert.ToBoolean(value);
                if (val)
                {
                    return new SolidColorBrush(Colors.Red);
                }
                else
                {
                    return new SolidColorBrush(Colors.Transparent);
                }
            }
            return null;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
Using simple binding to the converter and the property MyFlash we are done.

<Button Content="Start Blinking" Click="Button_Click" Background="{Binding Myflash,Converter={StaticResource MeConvetor}}"/>
All you need is to start the timer thread .....:)


  

אין תגובות:

הוסף רשומת תגובה