/// <summary> /// Classifies a sequence of elements using the features extracted from each element, /// and monitors cancellation requests. /// </summary> /// <typeparam name="T">The type of the elements to classify.</typeparam> /// <param name="sources">The elements to classify.</param> /// <param name="selector">The selector that converts elements into <typeparamref name="TFeatures"/> objects.</param> /// <param name="progress">The provider used to report a progress change. Can be <b>null</b>.</param> /// <param name="cancellationToken">The cancellationToken token used to notify the classifier that the operation should be canceled.</param> /// <returns> /// The sequence of <see cref="Answer"/> objects that contains the classification results. /// </returns> /// <exception cref="ArgumentNullException"> /// <para><paramref name="sources"/> is <b>null</b>.</para> /// <para>-or-</para> /// <para><paramref name="selector"/> is <b>null</b>.</para> /// </exception> public IEnumerable <Answer> Classify <T>( IEnumerable <T> sources, Func <T, CancellationToken, TFeatures> selector, IClassifierProgress <T> progress, CancellationToken cancellationToken) { if (sources == null) { throw new ArgumentNullException(nameof(sources)); } if (selector == null) { throw new ArgumentNullException(nameof(selector)); } return(sources .AsParallel() .AsOrdered() .WithCancellation(cancellationToken) .WithMergeOptions(ParallelMergeOptions.NotBuffered) .Select((source, index) => { Answer answer = null; progress?.OnClassifying(source, index); TFeatures features = selector(source, cancellationToken); if (features != null) { try { answer = this.Classify(features, cancellationToken); progress?.OnClassified(source, index, answer, null); } catch (Exception e) { progress?.OnClassified(source, index, null, e); } } return answer; })); }
/// <summary> /// Extracts features from a sequence of elements, /// provides progress information, /// and monitors cancellation requests. /// </summary> /// <typeparam name="T">The type of the elements to extract features from.</typeparam> /// <param name="sources">The elements to extract the features from.</param> /// <param name="selector">The selector that converts elements into <typeparamref name="TSource"/> objects.</param> /// <param name="progress">The provider used to report a progress change. Can be <b>null</b>.</param> /// <param name="cancellationToken">The cancellationToken token used to notify the classifier that the operation should be canceled.</param> /// <returns> /// The sequence of <typeparamref name="TFeatures"/> objects this method creates. /// </returns> /// <exception cref="ArgumentNullException"> /// <para><paramref name="sources"/> is <b>null</b>.</para> /// <para>-or-</para> /// <para><paramref name="selector"/> is <b>null</b>.</para> /// </exception> public IEnumerable <TFeatures> BuildFeatures <T>( IEnumerable <T> sources, Func <T, CancellationToken, TSource> selector, IClassifierProgress <T> progress, CancellationToken cancellationToken) { if (sources == null) { throw new ArgumentNullException(nameof(sources)); } if (selector == null) { throw new ArgumentNullException(nameof(selector)); } return(sources .AsParallel() .AsOrdered() .WithCancellation(cancellationToken) .WithMergeOptions(ParallelMergeOptions.NotBuffered) .Select((source, index) => { progress?.OnClassifying(source, index); TFeatures features = null; try { features = this.BuildFeatures(selector(source, cancellationToken), cancellationToken); progress?.OnClassified(source, index, null, null); } catch (Exception e) { progress?.OnClassified(source, index, null, e); } return features; })); }