WPF анимация тормозит другие окна

169
17 апреля 2019, 02:20

Есть основное окно, которое создает немодальное окно через Show(), на котором (немодальном окне) есть ProgressBar с IsIndeterminate="True".

Если перетаскивать основное окно мышью, то заметны фризы совпадающие по времени с анимацией, что и понятно, ведь все работает в одном потоке UI.

Но если создать то же самое немодальное окно в отдельном новом UI потоке (new Thread() со своим Dispatcher), то вместо ожидаемого "нет фризов" мы получаем еще большие фризы при перетаскивании основного окна.

Почему так? И как с этим бороться?

update: Подробный пример с размышлениями

Создаем окно MainWindow и отображаем его Show() (или оно само стартует как Application StartupUri="MainWindow.xaml"). Так у нас получается UI поток в котором работает форма.

Из MainWindow создаем NonModalWindow (и на нем расположен ProgressBar с IsIndeterminate, который и создает нагрузку в виде анимации)

var view = new NonModalWindow();
view.Show();

Получаем немодальное окно. Начинаем таскать мышью MainWindow и наблюдаем мелкие фризы, потому что NonModalWindow получает тот же UI поток и анимация и таскание обрабатывается одним Dispatcher

Cоздаем то же окно, но иначе - в новом потоке

var thread = new Thread(() =>
    {
        var view = new NonModalWindow();
        view.Closed += (sender2, e2) => win.Dispatcher.InvokeShutdown();
        view.Show();
        System.Windows.Threading.Dispatcher.Run();
    });
thread.SetApartmentState(ApartmentState.STA);
thread.Start();

у нового окна нет никакой связи с родителем, а также свой поток UI и свой Dispatcher.

Ожидается что фризы исчезнут, ведь анимация прогрессбара работает в своем потоке и первый поток UI и его Dispatcher никак не задевает. Но по факту получаем еще большие фризы.

update2: можно даже не таскать. открытие второго окна с прогрессбаром начинает влиять на анимацию первого. Вот если второе окно свернуть, то влияние исчезает. Будто бы используется общий поток, но где?

Answer 1

попробую подробнее отпишу тут

Есть 2 окно

там такая размтека для анимации

<Button RenderTransformOrigin="0.5,0.5" Height="100px" Width="150px" Loaded="FrameworkElement_OnLoaded">
            <Button.RenderTransform>
                <RotateTransform x:Name="AnimatedRotateTransform" Angle="0" />
            </Button.RenderTransform>
            <Button.Triggers>
                <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetName="AnimatedRotateTransform"
                                                 Storyboard.TargetProperty="Angle" 
                                                 To="360" Duration="0:0:1" RepeatBehavior="Forever" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
            </Button.Triggers>
        </Button>

При загрузке окна я стартую долгую операции типа запрос к серверу

private void FrameworkElement_OnLoaded(object sender, RoutedEventArgs e)
    {
            Thread.Sleep(20000);
            MessageBox.Show("End");
    }

и как ожидается анимации нет так как я заблочил ее и через скажет End

может что типа такова

private void FrameworkElement_OnLoaded(object sender, RoutedEventArgs e)
        {
            Task.Run(() => 
            {
                Thread.Sleep(20000);
                MessageBox.Show("End");
            });
        }

то у меня отработает анимация и моя операция и все плавно и хорошо

Я надеюсь верно понял вашу проблему

ну пробните это

private async  void RunTask()  
        {  
            textBox1.Text = "Task is going to run";  
            System.Threading.Thread.Sleep(1000);  
            await Task.Factory.StartNew(() =>  
            {  
                RunningTask();  
            });  
        }  
        private void RunningTask()  
        {  
            this.Dispatcher.Invoke((Action)(() =>  
            {  
                textBox1.Text = "Dispatcher is working";  
            }));  
        }  
READ ALSO
Выбор уникальных из List&lt;Dictionary&lt;string, string&gt;&gt;

Выбор уникальных из List<Dictionary<string, string>>

Подскажите как реализовать функцию отбора уникальных в

164
Unity JsonUtility ArgumentExсeption

Unity JsonUtility ArgumentExсeption

Задача: сделать десериализацию из строки json и поместить ее в переменнуюВсе дело происходит в Unity

126
Как добавить мою sql логику в этот код?

Как добавить мою sql логику в этот код?

Тут нужно проверку сделать product_id order_product_id customer_id Если получается пользователь с customer_id = 1 купил уже этот товар на который каждому пользователю...

163