Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю
Ниже приведен модифицированный код, где вместо литерального объекта делегата
Action<T><b>// Обработать данные изображений в параллельном режиме!</b>Parallel.ForEach(files, currentFile => { string filename = Path.GetFileName(currentFile);<b> // Этот оператор теперь приводит к проблеме! См. следующий раздел.</b><b> // this.Title = $" Processing {filename} on thread</b><b> // {Thread.CurrentThread.ManagedThreadld}"</b><b> // Thread.CurrentThread.ManagedThreadld);</b> using (Bitmap bitmap = new Bitmap( currentFile)) using (Bitmap bitmap = new Bitmap(currentFile)) { bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone); bitmap.Save(Path.Combine(outputDirectory, filename)); } });Доступ к элементам пользовательского интерфейса во вторичных потоках
Вы наверняка заметили, что в показанном выше коде закомментированы строки, которые обновляют заголовок главного окна значением идентификатора текущего выполняющегося потока. Как упоминалось ранее, элементы управления графического пользовательского интерфейса привязаны к потоку, где они были созданы. Если вторичные потоки пытаются получить доступ к элементу управления, который они напрямую не создавали, то при отладке программного обеспечения возникают ошибки времени выполнения. С другой стороны, если запустить приложение (нажатием <Ctrl+F5>), тогда первоначальный код может и не вызвать каких-либо проблем.
На заметку! Не лишним будет повторить: при отладке многопоточного приложения вы иногда будете получать ошибки, когда вторичный поток обращается к элементу управления, созданному в первичном потоке. Однако часто после запуска приложение может выглядеть функционирующим корректно (или же довольно скоро может возникнуть ошибка). Если не предпринять меры предосторожности (описанные далее), то приложение в подобных обстоятельствах может потенциально сгенерировать ошибку во время выполнения.
Один из подходов, который можно использовать для предоставления вторичным потокам доступа к элементам управления в безопасной к потокам манере, предусматривает применение другого приема — анонимного делегата. Родительский класс
ControlDispatcherInvoke()System.Delegate<b>// Этот код больше не работает!</b><b>// this.Title = $"Processing {filename} on thread {Thread.</b><b>// CurrentThread.ManagedThreadld}";</b><b>// Вызвать Invoke() на объекте Dispatcher, чтобы позволить вторичным потокам</b><b>// получать доступ к элементам управления в безопасной к потокам манере.</b>Dispatcher?.Invoke(() =>{ this.Title = $"Processing {filename}";});using (Bitmap bitmap = new Bitmap(currentFile)){ bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone); bitmap.Save(Path.Combine(outputDirectory, filename));}Теперь после запуска программы библиотека TPL распределит рабочую нагрузку по множеству потоков из пула, используя столько процессоров, сколько возможно. Тем не менее, поскольку заголовок
TitleTitleКласс Task
Класс
TaskClickButtonprivate void cmdProcess_Click(object sender, EventArgs e){ // Запустить новую "задачу" для обработки файлов. Task.Factory.StartNew(() => ProcessFiles()); // Можно записать и так: // Task.Factory.StartNew(ProcessFiles);}Свойство
FactoryTaskTaskFactoryStartNew()Action<T>Похожие книги на "Язык программирования C#9 и платформа .NET5", Троелсен Эндрю
Троелсен Эндрю читать все книги автора по порядку
Троелсен Эндрю - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки mir-knigi.info.