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


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. Соберите проект и запустите его.