2014-08-19 1 views
7

Я видел этот код, проверить состояние с помощью 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; 
     } 

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

Однако - это (другого) код делает "отделку - как можно скорее" + отменить другую будущую работу:

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

Вопрос:

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

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

+2

Вы смотрите на неправильный источник. Вам нужно посмотреть [ParalellEnumerable.Any] (http://referencesource.microsoft.com/#System.Core/System/Linq/ParallelEnumerable.cs), который намного сложнее, чем то, что вы видите «Enumerable.Any» –

ответ

8

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

Исходный код ссылки для ParallelEnumerable.Any: here.

Когда вы копаете, например. в класс AnyAllSearchOperatorEnumerator, вы видите, что флаг resultFoundFlag используется для tell other workers that a result is found, поэтому they can stop searching.

+0

ouch .... that ws my fear. Я искал неправильный код :-) –

5

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

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


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

4

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

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