public void Cancellation_Test(int jobCount) { int sequenceLength = jobCount * 10; int cancelTreshold = jobCount * 2; int resultTreshold = jobCount * 3; var cancellationEvent = new AutoResetEvent(false); var cancellationToken = new CancellationToken(); List <int> results = new List <int>(); Task task = Task.Run(() => { IEnumerable <int> values = Sequence(sequenceLength, 5) .AsParallel(jobCount) .AsEnumerable(cancellationToken); foreach (int value in values) { results.Add(value); if (results.Count == cancelTreshold) { cancellationEvent.Set(); } } }); cancellationEvent.WaitOne(); cancellationToken.Cancel(); task.Wait(timeout) .Should().BeTrue("Timeout"); results.Should().HaveCountLessOrEqualTo(resultTreshold); }
public void Run(CancellationToken cancellationToken, ProfilingType profilingType) { Guard.NotNull(cancellationToken, nameof(cancellationToken)); if (thread != null) { throw new InvalidOperationException(); } thread = new Thread(() => { try { Profiler profiler = profilingType != ProfilingType.None ? new Profiler(name, profilingType) : null; Do(cancellationToken, profiler); } catch (Exception error) { this.error = error; cancellationToken.Cancel(); } finally { outputChannel.Finish(); } }) { Name = name, IsBackground = true }; thread.Start(); }
public IEnumerable <T> AsEnumerable(CancellationToken cancellationToken = null, IJobLogger logger = null) { if (cancellationToken == null) { cancellationToken = new CancellationToken(); } var errorHandler = new ErrorHandler(); Job <T>[] jobs = Enumerable.Range(1, jobCount) .Select(i => new Job <T>($"{i}", enumeration, cancellationToken)) .ToArray(); while (true) { if (HandleErrors(jobs, errorHandler)) { cancellationToken.Cancel(); break; } if (logger != null) { logger.LogResultsCount(jobs.Select(job => job.ResultsCount).Sum()); } List <T> results = new List <T>(jobs.Length); foreach (var job in jobs) { if (job.TryGetResult(out T result)) { results.Add(result); } } foreach (T result in results) { yield return(result); } if (jobs.All(job => job.IsFinished)) { HandleErrors(jobs, errorHandler); break; } else { Thread.Sleep(5); } } foreach (var job in jobs) { job.Dispose(); } errorHandler.ThrowIfFailed(); }
void Do(CancellationToken cancellationToken, Profiler profiler) { bool Read(out T data) { bool finished = true; profiler?.BeginWatch(ProfilingType.Read); try { finished = inputChannel.Read(out data, profiler); } finally { profiler?.EndWatch(ProfilingType.Read); } return(finished); } U Transform(T data) { U result = default(U); profiler?.BeginWatch(ProfilingType.Transform); try { result = transform(data); } finally { profiler?.EndWatch(ProfilingType.Transform); } return(result); } void Write(U data) { profiler?.BeginWatch(ProfilingType.Write); try { outputChannel.Write(data); } finally { profiler?.EndWatch(ProfilingType.Write); } } while (Read(out T data)) { if (cancellationToken.IsCancelled) { break; } Write(Transform(data)); } }
public Job(string name, IEnumerable <T> enumeration, CancellationToken cancellationToken) { Guard.NotNull(name, nameof(name)); Guard.NotNull(enumeration, nameof(enumeration)); Guard.NotNull(cancellationToken, nameof(cancellationToken)); this.enumeration = enumeration; this.cancellationToken = cancellationToken; thread = new Thread(Run) { Name = name, IsBackground = true }; thread.Start(); }