AsParallel () и Any ()?

Я видел этот код, который проверяет условие с помощью AsParallel() и Any():

bool IsAnyDeviceConnected()
{
   return m_devices.Any(d => d.IsConnected);
}

и чтобы сделать это быстрее:

bool IsAnyDeviceConnected()
{
   return m_devices.AsParallel().Any(d => d.IsConnected);
}

Но глядя на Any():

 internal static bool Any<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
            foreach (T element in source) {
                if (predicate(element)) {
                    return true;
                }
            }
            return false;
        }

Я не вижу (очевидно), что он действительно заботится о отмене других рабочих процессов - после того, как он обнаружен.

Однако этот (другой) код выполняет «завершение - как можно скорее» + отменяет другие работы в будущем:

bool IsAnyDeviceConnected()
{
   var res = Parallel.ForEach(m_devices,
      (d,loopState) => {  
         if (d.IsConnected) 
            loopState.Stop();
      });
   return !res.IsCompleted;
}

Вопрос:

Моя диагностика верна? Делает Any() - однажды найденный элемент не отменяет другие потоки (в контексте AsParallel)

nb, я опасаюсь, что смотрю не на тот исходный код.


person Royi Namir    schedule 19.08.2014    source источник
comment
Вы смотрите не на тот источник. Вам нужно посмотреть ParalellEnumerable.Any, что является способом сложнее, чем то, что вы видите Enumerable.Any   -  person Sriram Sakthivel    schedule 19.08.2014


Ответы (3)


AsParallel() возвращает ParallelQuery, поэтому, если вы позвоните AsParallel().Any(...), вы вызываем не Enumerable.Any, а ParallelEnumerable.Any.

Исходный код ссылки для ParallelEnumerable.Any находится здесь.

Когда вы копаете, например, в класс AnyAllSearchOperatorEnumerator, вы увидите, что флаг называется resultFoundFlag используется, чтобы сообщить другим рабочим, что результат найден, чтобы прекратить поиск.

person sloth    schedule 19.08.2014

Вы смотрите не на тот код. AsParallel возвращает ParallelQuery<TSource>, а ParellelQuery имеет другую перегрузку для Any.

Any создает новый AnyAllSearchOperator объект и агрегирует его. Если вы углубитесь в эту цепочку вызовов методов и объектов, вы обнаружите, что QueryOpeningEnumerator действительно поддерживает отмену.


К сожалению, ссылки на источники ссылок на эти конкретные функции-члены содержат ошибки.

person Dirk    schedule 19.08.2014

Вы смотрите не на тот код. ParallelEnumerable.AsParallel возвращает ParallelQuery<>. ParallelEnumerable также определяет свой собственный Any метод расширения.

Чтобы указать отмену, степень параллелизма и т. Д., Вам необходимо использовать методы расширения WithXXX в ParallelEnumerable, такие как WithCancellation и WithDegreeOfParallelism. ParallelEnumerable.Any не позволяет вам указывать эти параметры для сохранения подписи, аналогичной Enumerable.Any

person Panagiotis Kanavos    schedule 19.08.2014