Поделиться через


Non-generic ParallelForEach (негенерический ParallelForEach)

.NET Framework 4.6.1 поставляется с набором действий управления потоком на панели элементов, включая ParallelForEach<T>, который позволяет выполнять итерации по коллекциям IEnumerable<T>.

ParallelForEach<T> требует, чтобы его Values свойство было типом IEnumerable<T>. Это предотвращает итерацию пользователей над структурами данных, реализующими IEnumerable<T> интерфейс (например, ArrayList). Необобщённая версия ParallelForEach<T> преодолевает это требование, повышая сложность на уровне среды выполнения для обеспечения совместимости типов значений в коллекции.

В примере NonGenericParallelForEach показано, как реализовать не универсальное ParallelForEach<T> действие и его конструктор. Это действие можно использовать для итерации ArrayList.

Задача ParallelForEach

Инструкция C#/Visual Basic foreach перечисляет элементы коллекции, выполняя внедренную инструкцию для каждого элемента коллекции. Эквивалентные действия WF: ForEach<T> и ParallelForEach<T>. Действие ForEach<T> содержит список значений и текст. Во время выполнения список итерируется, и тело выполняется для каждого значения в списке.

ParallelForEach<T> имеет CompletionCondition, чтобы ParallelForEach<T> активность могла завершиться рано, если оценка CompletionCondition возвращает true. Оценка CompletionCondition производится после завершения каждой итерации.

В большинстве случаев универсальная версия действия должна быть предпочтительным решением, так как она охватывает большинство сценариев, в которых он используется, и обеспечивает проверку типов во время компиляции. Не универсальная версия может использоваться для итерации типов, реализующих не универсальный IEnumerable интерфейс.

Определение класса

В следующем примере кода показано определение необобщённого ParallelForEach действия.

[ContentProperty("Body")]
public class ParallelForEach : NativeActivity
{
    [RequiredArgument]
    [DefaultValue(null)]
    InArgument<IEnumerable> Values { get; set; }

    [DefaultValue(null)]
    [DependsOn("Values")]
    public Activity<bool> CompletionCondition
    [DefaultValue(null)]
    [DependsOn("CompletionCondition")]
    ActivityAction<object> Body { get; set; }
}

Текст (необязательно)
Тип ActivityActionObject, который выполняется для каждого элемента в коллекции. Каждый отдельный элемент передается в Body через его свойство Argument.

Значения (необязательно)
Коллекция элементов, перебираемых в процессе итерации. Обеспечение того, чтобы все элементы коллекции были совместимыми типами во время выполнения.

Условие завершения (необязательно)
Свойство CompletionCondition вычисляется после завершения итерации. Если она оценивается true, то запланированные ожидающие итерации отменяются. Если это свойство не задано, все операции в коллекции ветвей выполняются до завершения.

Пример использования ParallelForEach

В следующем коде показано, как использовать действие ParallelForEach в приложении.

string[] names = { "bill", "steve", "ray" };

DelegateInArgument<object> iterationVariable = new DelegateInArgument<object>() { Name = "iterationVariable" };

Activity sampleUsage =
    new ParallelForEach
    {
       Values = new InArgument<IEnumerable>(c=> names),
       Body = new ActivityAction<object>
       {
           Argument = iterationVariable,
           Handler = new WriteLine
           {
               Text = new InArgument<string>(env => string.Format("Hello {0}",                                                               iterationVariable.Get(env)))
           }
       }
   };

Дизайнер ParallelForEach

Конструктор действий в примере по внешнему виду похож на конструктор, предоставленный для встроенного ParallelForEach<T> действия. Конструктор отображается на панели элементов в категории «Примеры», «Неуниверсальные действия». Конструктор называется ParallelForEachWithBodyFactory на панели элементов, так как действие предоставляется IActivityTemplateFactory на панели элементов, создающей действие с правильно настроенным ActivityAction.

public sealed class ParallelForEachWithBodyFactory : IActivityTemplateFactory
{
    public Activity Create(DependencyObject target)
    {
        return new Microsoft.Samples.Activities.Statements.ParallelForEach()
        {
            Body = new ActivityAction<object>()
            {
                Argument = new DelegateInArgument<object>()
                {
                    Name = "item"
                }
            }
        };
    }
}

Запуск примера

  1. Задайте выбранный проект в качестве запускаемого проекта решения.

    1. CodeTestClient показывает, как использовать действие с помощью кода.

    2. DesignerTestClient показывает, как использовать активность в конструкторе.

  2. Соберите проект и запустите его.