Вдобавок понадобится применять делегаты System.Func и System.Action для указания целевого метода, который будет вызываться при обработке данных. Делегат Func уже встречался в главе 13 во время исследования технологии LINQ to Objects. Вспомните, что Func представляет метод, который возвращает значение и принимает различное количество аргументов. Делегат Action похож на Func в том, что позволяет задавать метод, принимающий несколько параметров, но данный метод должен возвращать void.
Хотя можно было бы вызывать методы Parallel.For() и Parallel.ForEach() и передавать им строго типизированный объект делегата Func или Action, задача программирования упрощается за счет использования подходящих анонимных методов или лямбда-выражений С#.
Обеспечение параллелизма данных с помощью класса Parallel
Первое применение библиотеки TPL связано с обеспечением Parallel.For() или Parallel.ForEach(). Предположим, что необходимо выполнить некоторые трудоемкие операции файлового ввода-вывода. В частности, требуется загрузить в память большое число файлов *.jpg, повернуть содержащиеся в них изображения и сохранить модифицированные данные изображений в новом месте.
Задача будет решаться с использованием графического пользовательского интерфейса, так что вы увидите, как применять "анонимные делегаты", позволяющие вторичным потокам обновлять первичный поток пользовательского интерфейса.
На заметку! При построении многопоточного приложения с графическим пользовательским интерфейсом вторичные потоки никогда не смогут напрямую обращаться к элементам управления пользовательского интерфейса. Причина в том, что элементы управления (кнопки, текстовые поля, метки, индикаторы хода работ и т.п.) привязаны к потоку, в котором они создавались. В следующем примере иллюстрируется один из способов обеспечения для вторичных потоков возможности получать доступ к элементам пользовательского интерфейса в безопасной к потокам манере. Во время рассмотрения ключевых слов async и await языка C# будет предложен более простой подход.
В целях иллюстрации создайте приложение Windows Presentation Foundation (WPF) по имени DataParallelismWithForEach, выбрав шаблон WPF Арр (.NET Core). Чтобы создать проект и добавить его к решению с помощью командной строки, используйте следующие команды:
dotnet new wpf -lang c# -n DataParallelismWithForEach
-o .\DataParallelismWithForEach -f
net5.0
dotnet sln .\Chapter15_AllProjects.sln add .\DataParallelismWithForEach
На заметку! Инфраструктура Windows Presentation Foundation (WPF) в текущей версии .NET Core предназначена только для Windows и будет подробно рассматриваться в главах 24-28. Если вы еще не работали с WPF, то здесь описано все, что необходимо для данного примера. Разработка приложений WPF ведется в среде Visual Studio Code, хотя никаких визуальных конструкторов там не предусмотрено. Чтобы получить больший опыт разработки приложений WPF, рекомендуется использовать Visual Studio 2019.
Дважды щелкните на имени файла MainWindow.xaml в окне Solution Explorer и поместите в него показанное далее содержимое XAML:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:DataParallelismWithForEach"
mc:Ignorable="d"
Title="Fun with TPL" Height="400" Width="800">
Feel free to type here while the images are processed...
Margin="10,10,0,10"
Click="cmdCancel_Click">
Cancel
Margin="0,10,10,10"
Click="cmdProcess_Click">
Click to Flip Your Images!