Модераторы: gambit, Kefir, Partizan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> WPF - Task, Timer и BackgroundWorker совместно, Как правильно их использовать 
:(
    Опции темы
NEt_Hunter
Дата 30.8.2013, 15:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 106
Регистрация: 9.10.2006
Где: Германия

Репутация: нет
Всего: нет



Привет всем. Совсем недавно начал изучать работу с потоками в WPF и возникли немного вопросов, на которые, надеюсь, смогу ответить с вашей помощью. Задача программы выполнить определенную работу каждые 10 секунд. Разбить эту работу на несколько частей используя потоки (Task) и при этом использовать BackgroundWorker чтобы пользовательский интерфейс не зависал во время выполнения работ. В интернете нашел много пример работы с тасками, но не смог найти несложные примеры, которые бы обьяснили как таски правильно использовать с таймером, BackgroundWorker и локами конечно. Для ясности привожу пример, которую написал, чтобы вы могли посмотреть и посоветовать правильно ли написан код. Благодаря вашим советам я смогу лучше понять как работает многопоточность в WPF. Жду с нетерпением ваших сообщением. Буду благодарен за любую предоставленную помощь.



Код

namespace timer_and_thread
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            DispatcherTimer TimerObject;
            Task[] tasks;
            readonly object _countLock = new object();
            int[] Summ = new int[10];
            int Index = 0;
 
            public MainWindow()
            {
                InitializeComponent();
                TimerObject = new DispatcherTimer();
                TimerObject.Tick += new EventHandler(timer_Elapsed);
                TimerObject.Interval = new TimeSpan(0, 0, 10);
            }
 
            // вызвать метод каждые 10 секунд
            private void timer_Elapsed(object sender, EventArgs e)
            {
                TimerObject.Stop();
 
                BackgroundWorker backgroundWorkerObject = new BackgroundWorker();
                backgroundWorkerObject.DoWork += new DoWorkEventHandler(StartThreads);
                backgroundWorkerObject.RunWorkerAsync();
 
                TimerObject.Start();
            }
 
 
            private void StartThreads(object sender, DoWorkEventArgs e)
            {
                tasks = new Task[4];
                tasks[0] = Task.Factory.StartNew(() => DoSomeLongWork());
                tasks[1] = Task.Factory.StartNew(() => DoSomeLongWork());
                tasks[2] = Task.Factory.StartNew(() => DoSomeLongWork());
                tasks[3] = Task.Factory.StartNew(() => DoSomeLongWork());
 
                // Даем задачам 1 секунду для их запуска 
                Thread.Sleep(1000);
            }
 
            private void DoSomeLongWork()
            {
                while (Index < Summ.Length)
                {
                    int localIndex = 0;
 
                    // блокируем глобальную переменную Index 
                    lock (_countLock)
                    {
                        localIndex = Index;
                        Index++;
                    }
 
                    // Я написал простой пример работы. Тут может быть большая вычислительная работа.
                    Random rnd = new Random();
                    int someResult = rnd.Next(1, 100000);
 
                    //  блокируем глобальную переменную Summ для записи в нее вычисленного результата
                    lock (_countLock)
                    {
                        Summ[localIndex] = someResult;
                    }      
                }
            }
 
            // Кнопка, с помощью которой запускаю таймер и начинается работа приложения
            private void Start_Button_Click_1(object sender, RoutedEventArgs e)
            {
                TimerObject.Start();
            }
 
        }
    }


PM MAIL ICQ   Вверх
Kefir
Дата 13.12.2013, 11:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


«Hakuna Matata»
***


Профиль
Группа: Комодератор
Сообщений: 1878
Регистрация: 25.1.2003
Где: Tampere, Suomi

Репутация: 22
Всего: 87



  • Если есть необходимость заполнять массив из разных тредлов - лучше пользуйтесь неймспейсом System.Collections.Concurrent - МС уже сделали за вас всю грязную работы и классы там тред-сейфные.
  • Строки 25, 31 - не совсем ясно зачем останавливать таймер? Ибо это удаляет нас от заявленных "каждых 10-ти секунд". Ну и вообще - ненужные какие-то строки.
  • Строки 27-29 - зачем вам отдельный бакграунд воркер для запуска тредов? Код запуска тредов очень прост (просто создает таски) и я не вижу необходимости выделять его в отдельный тред.
  • Строка 44 - что значит "даём 1 секунду"? Таски начали работать потихоньку уже (теоретически) - зачем вам ждать целую секунду непонятно чего
  • Внутри DoSomeLongWork стоит таки заменить ваш массив + индекс на какую-нибудь конкуррентную коллекцию. Таким образом весь метод можно сильно упростить попутно избавившись от мороки с локами.

PM MAIL WWW Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | WPF и Silverlight | Следующая тема »


 




[ Время генерации скрипта: 0.1009 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.