C#: Работа с потоками (2).

Краткая шпаргалка — часть 2.

Использование TPL — Task parallel library — System.Threading.Tasks позволяет делать параллельный код без необходимости напрямую иметь дело с потоками или пулами потоков. Ключевым классом в TPL является System.Threading.Tasks.Parallel позволяющий делать итерацию по объектам IEnumerable в параллельном режиме. Контейнер может быть массивом, коллекцией или результатом запроса LINQ. Делегаты System.Func и System.Action понадобит­ся чтобы задать целевой метод, который будет вызываться для обработки данных.

private void button1_Click(object sender, EventArgs e)
{
    ProcessFiles();
}

private void ProcessFiles()
{
    // Загрузить все файлы *.jpg и создать новую папку для модифицированных данных.
    string[] files = Directory.GetFiles(@"D:\src1", "*.jpg",SearchOption.AllDirectories); 
    string newDir = @"D:\ModifiedPictures\src1";Directory.CreateDirectory(newDir);
            
   //обработка в параллелном режиме, в качестве делегата используем лямбда-выражение
    //Можно Parallel.For
    Parallel.ForEach(files, currentFile =>
    {
         string fileName = Path.GetFileName(currentFile);

         using (Bitmap bitmap = new Bitmap(currentFile))
         {
               bitmap.RotateFlip(RotateFlipType.Rotate90FlipNone);
               bitmap.Save(Path.Combine(newDir, fileName));
               //К родительской форме из потока можно добраться только из метода Incvoke
               //обеспечивающий потокобезопасность
               //Вызвать Invoke на объекте Form, чтобы позволить вторичным потокам
               // получать доступ к элементам управления в безопасной к потокам манере.
               //WPF  для  той  же  цели  должен  использоваться  вызов this.Dispatcher. Invoke()
               this.Invoke
               (
                      //используем анонимный делегат
                      (Action)delegate
                      {
                            this.Text = string.Format("Processing {0} on thread {1}", fileName, Thread.CurrentThread.ManagedThreadId);
                      }
                );

          }
      }
   );
        
}

Есть один недостаток: при клике по кнопке форма становиться неактивной до тех пор, пока все процессы по преобразованию картинок не закончатся. Чтобы этого не произошло, надо функцию запустить в отдельном процессе.

Свойство Factory класса Task возвращает объект TaskFactory. При вызове метода StartNow() ему передается делегат Action (здесь это скрыто подходящим лямбда-выражением), который указывает на метод, подлежащий вызову в асинхронной манере.

private void button2_Click(object sender, EventArgs e)
{
    // Запустить новую "задачу" для обработки файлов.
    //Свойство Factory класса Task возвращает  объект TaskFactory.  
    //При  вызове  методаStartNow()  ему  передается  делегат Action<T>
    //(здесь  это  скрыто  подходящим  лямбда-выражением),  
    //который  указывает  на  метод,  подлежащий  вызову  в  асинхронной  манере.
      Task.Factory.StartNew(() =>{
           ProcessFiles();
      });
}

Теперь отменим запущенные процессы. Создадим объект CancellationTokenSource и используем его для остановки запущенных процессов, передавая его в составе объекта ParallelOptions запущенному процессу из пула процессов.

private CancellationTokenSource cancelToken = new CancellationTokenSource();

 private void Cansel_Click(object sender, EventArgs e)
        {
            // Это будет использоваться для сообщения всем рабочим потокам// о необходимости останова!
            cancelToken.Cancel();
        }

 private void ProcessFiles1()
        {
            // Использовать экземпляр ParallelOptions для хранения CancellationToken.
            ParallelOptions parOpts = new ParallelOptions();
            parOpts.CancellationToken = cancelToken.Token;
            parOpts.MaxDegreeOfParallelism = System.Environment.ProcessorCount;
            // Загрузить все файлы *.jpg и создать новую папку для модифицированных данных. 
            string[] files = Directory.GetFiles(@"D:\src1", "*.jpg",SearchOption.AllDirectories); 
            string newDir = @"D:\ModifiedPictures\src1";Directory.CreateDirectory(newDir);
            
            try
            {
                // Обработать данные изображения в параллельном режиме!
                Parallel.ForEach(files, parOpts, currentFile =>
                {
                    parOpts.CancellationToken.ThrowIfCancellationRequested();
                    string filename = Path.GetFileName(currentFile); 
                    using (Bitmap bitmap = new Bitmap(currentFile))
                    {
                        bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
                        bitmap.Save(Path.Combine(newDir, filename));
                        this.Invoke(
                        (Action)delegate 
                        {
                            this.Text = string.Format("Processing {0} on thread {1}", filename, Thread.CurrentThread.ManagedThreadId);
                        }
                        );
                    }
                }
                );
            }
            catch (OperationCanceledException ex)
            {
                this.Invoke
                (
                    (Action)delegate
                    {
                        this.Text = ex.Message;
                    }
                 );
            }
        }

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Найти на сайте
Со страниц сайта
Метки
хохмаУмные мыслиармейский юморДела семейныеДокторинформацияой болитфольклорВовочка & kidsВадим ЗверевПолитическиеСтатусы ВКотактеСобрание скороговорокБольшие и малые народностиПро животныхЗаконы МерфиженщиныПро это...Забойный наборНиколай ФоменкоВсякая всякотаалкоманы-наркоголикиВиктор ШендеровичПро услуги и рестораныБородатые анекдотыавтомобилистыТуристы и турыИскусство и киноКозьма ПрутковПро студентовПро работуОмар ХайямЧерномырдинСтатусы про женщин и мужчинВ общественном транспортеПро сумасшедшихСтанислав Ежи ЛецКриминальныеПро ШтирлицаСтас ЯнковскийСмешные статусыДурацкие законыПро юристовпро самолетыПечалькаПро братковХорошие советыНе та ориентацияМарк ТвенСтатусы про жизньНа селеКрасноармейскиеГусары и поручикиДразнилкиИностранные анекдотыСказочныеХрюн МоржовФрансуа де ЛарошфукоЧерный юморЖан-Жак РуссоОхота и рыбалкаПрограммистыЛеди и джентельменыСпортМультяшкиНа бога надейся...БизнесСчиталкиУильям ШекспирГеоргий ФрумкерФрансис БэконШутливая лотереяДикий западПраздникиБедные и богатыеРаневскаяПьер Огюстен Карон де БомаршеСоветы и ответыДикариИсторические анекдотыНикколо МакиавеллиНаполеон БонапартЗагадкиsongswordpresstraditionalpluginпоговоркиC#старостьЧастушкиmysqlbackendjavascripthostingsshajaxphpстатистикапандемия
Больше Меньше
Архивы
Рейтинг@Mail.ru