Информация об изменениях

Сообщение Re: wpf, выполнение действий в разных потоках от 23.07.2016 22:02

Изменено 23.07.2016 22:30 VladCore

Здравствуйте, alex1010, Вы писали:

A>Есть, скажем, видеопанель, на которую выведены изображения от 5 ip-камер. Интерфейс построен на wpf.

A>При создании экземпляров камер/подключении к ним, возможны задержки до 15-20 секунд.
A>В результате, если тупо все делать в одно потоке, вся панель подвисает на это время, пока не пройдет инициализация камеры.
A>Логичное решение — вынести создание каждой камеры в отдельный поток.

A>Вопрос — на каком уровне это можно сделать?


На любом Делается так же как ина самом первом WPF:

using System;
using System.Windows;

namespace WpfAsyncSample
{
    using System.Threading;
    using System.Windows.Threading;

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.Async(Action: () =>
            {
                // Долго инициализируемся и падаем
                Thread.Sleep(2000);
                this.RunSyncronously(() => label.Content = "Stage 1 done");
                Thread.Sleep(3000);
                this.RunSyncronously(() => label.Content = "Stage 2 done");
                Thread.Sleep(4000);
                throw new Exception();
            },
            Then: optionalException =>
            {
                // Мы в UI потоке
                if (optionalException == null)
                {
                    // Всё ok.
                }
                else
                {
                    // Инициализация упала.
                }
            });
        }
    }

    public static class DispatcableExtentions
    {
        public static void Async(this DispatcherObject ui, Action Action = null, Action<Exception> Then = null)
        {
            if (Action == null)
                throw new ArgumentNullException("AsyncAction");

            ThreadPool.QueueUserWorkItem(state =>
            {
                Exception ex;
                try
                {
                    Action();
                    ex = null;
                }
                catch (Exception ex2)
                {
                    ex = ex2;
                }

                if (Then != null)
                    ui.Dispatcher.BeginInvoke(new Action(() => { Then(ex); }));
            });
        }

        public static void RunSyncronously(this DispatcherObject ui, Action SyncAction)
        {
            ui.Dispatcher.BeginInvoke(new Action(SyncAction));
        }

    }
}


Надеюсь ненадо отдельно указывать про то что вместо this.Run() можно писать любой_UI_элемент.Run()

Если надо результаты успешной инициализации передать в UI поток, пользуйтесь замыканиями. Надо показать как?

A>Я могу часть элементов визуальных, относящихся к wpf, вынести в отдельный поток?


не нужно.
Re: wpf, выполнение действий в разных потоках
Здравствуйте, alex1010, Вы писали:

A>Есть, скажем, видеопанель, на которую выведены изображения от 5 ip-камер. Интерфейс построен на wpf.

A>При создании экземпляров камер/подключении к ним, возможны задержки до 15-20 секунд.
A>В результате, если тупо все делать в одно потоке, вся панель подвисает на это время, пока не пройдет инициализация камеры.
A>Логичное решение — вынести создание каждой камеры в отдельный поток.

A>Вопрос — на каком уровне это можно сделать?


На любом Делается так же как ина самом первом WPF:

using System;
using System.Windows;

namespace WpfAsyncSample
{
    using System.Threading;
    using System.Windows.Threading;

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.Async(Action: () =>
            {
                // Долго инициализируемся и падаем
                Thread.Sleep(2000);
                this.RunSyncronously(() => label.Content = "Stage 1 done");

                Thread.Sleep(3000);
                this.RunSyncronously(() => label.Content = "Stage 2 done");

                Thread.Sleep(4000);
                throw new Exception("Stage 3 failed");
            },
            Then: optionalException =>
            {
                // Мы в UI потоке
                if (optionalException == null)
                {
                    // Всё ok.
                }
                else
                {
                    // Инициализация упала.
                }
            });
        }
    }

    public static class DispatcableExtentions
    {
        public static void Async(this DispatcherObject ui, Action Action = null, Action<Exception> Then = null)
        {
            if (Action == null)
                throw new ArgumentNullException("AsyncAction");

            ThreadPool.QueueUserWorkItem(state =>
            {
                Exception ex;
                try
                {
                    Action();
                    ex = null;
                }
                catch (Exception ex2)
                {
                    ex = ex2;
                }

                if (Then != null)
                    ui.Dispatcher.BeginInvoke(new Action(() => { Then(ex); }));
            });
        }

        public static void RunSyncronously(this DispatcherObject ui, Action SyncAction)
        {
            ui.Dispatcher.BeginInvoke(new Action(SyncAction));
        }

    }
}


Надеюсь ненадо отдельно указывать про то что вместо this.Run() можно писать любой_UI_элемент.Run()

Если надо результаты успешной инициализации передать в UI поток, пользуйтесь замыканиями. Надо показать как?

A>Я могу часть элементов визуальных, относящихся к wpf, вынести в отдельный поток?


не нужно.