public void ConfigureConcurrency() { var result = new ConcurrentQueue <string>(); var job = new ParallelJob(new ConsoleLogProvider()) .AddTask("a", () => { Task.Delay(50).Wait(); result.Enqueue("a"); }) .AddTask("b", () => result.Enqueue("b")) .AddTask("c", () => result.Enqueue("c"), new[] { "a" }); job.RunAllTasks(0); Assert.AreEqual("bac", string.Concat(result)); result = new ConcurrentQueue <string>(); job.RunAllTasks(1); Assert.AreEqual("abc", string.Concat(result)); }
public void UnresolvableDependencies() { var result = new ConcurrentQueue <string>(); var job = new ParallelJob(new ConsoleLogProvider()) .AddTask("a", () => result.Enqueue("a"), new[] { "c", "d", "e" }) .AddTask("b", () => result.Enqueue("b"), new[] { "c", "d", "e" }) .AddTask("c", () => result.Enqueue("c"), new[] { "d", "e" }) .AddTask("d", () => result.Enqueue("d"), new[] { "a" }) .AddTask("e", () => result.Enqueue("e")); TestUtility.ShouldFail <InvalidOperationException>(() => job.RunAllTasks(), "Unable to resolve required task dependencies"); Assert.AreEqual("e", string.Concat(result)); }
public void ComplexDependencies() { var result = new ConcurrentQueue <string>(); var job = new ParallelJob(new ConsoleLogProvider()) .AddTask("a", () => result.Enqueue("a"), new[] { "c", "d", "e" }) .AddTask("b", () => result.Enqueue("b"), new[] { "c", "d", "e" }) .AddTask("c", () => result.Enqueue("c"), new[] { "d", "e" }) .AddTask("d", () => result.Enqueue("d"), new[] { "e" }) .AddTask("e", () => result.Enqueue("e")); job.RunAllTasks(); var sequence = string.Concat(result); Assert.IsTrue(sequence == "edcab" || sequence == "edcba"); }
public void StopOnException() { var result = new ConcurrentQueue <string>(); var job = new ParallelJob(new ConsoleLogProvider()) .AddTask("a", () => { Task.Delay(50).Wait(); result.Enqueue("a"); }) .AddTask("b", () => { result.Enqueue("b"); throw new InvalidOperationException("Test exception"); }) .AddTask("c", () => result.Enqueue("c"), new[] { "a" }); var e = TestUtility.ShouldFail <InvalidOperationException>(() => job.RunAllTasks(), "Test exception"); Assert.AreEqual("ab", string.Concat(result.OrderBy(a => a))); }
public void CorrectlyCancels() { var lockAStart = new SemaphoreSlim(0, 1); var lockAFinished = new SemaphoreSlim(0, 1); var lockBFinished = new SemaphoreSlim(0, 1); var result = new ConcurrentQueue <string>(); var job = new ParallelJob(new ConsoleLogProvider()) .AddTask("a", () => { lockAStart.Wait(); result.Enqueue("a"); lockAFinished.Release(); }) .AddTask("b", () => { result.Enqueue("b"); lockBFinished.Release(); }) .AddTask("c", () => result.Enqueue("c"), new[] { "a" }); var cancellationTokenSource = new CancellationTokenSource(); var task = Task.Run(() => job.RunAllTasks(0, cancellationTokenSource.Token)); lockBFinished.Wait(); // Wait for "b" to finish. cancellationTokenSource.Cancel(); var e = TestUtility.ShouldFail <AggregateException>(() => task.Wait()); Assert.IsTrue(e.InnerException is OperationCanceledException); // Only "b" should be completed. "a" is waiting for lock, "c" i waiting for "a". Assert.AreEqual("b", TestUtility.Dump(result)); lockAStart.Release(); // Allow "a" to run now. // "a" is expected to complete also, since it has been started prior to cancellation. lockAFinished.Wait(); // Wait for "a" to finish. Thread.Sleep(50); // Wait a little longer, but "c" should still not start, because it had not started prior to cancellation. Assert.AreEqual("b, a", TestUtility.Dump(result)); }
public void CorrectlyCancels() { var lockAStart = new SemaphoreSlim(0, 1); var lockAFinished = new SemaphoreSlim(0, 1); var lockBFinished = new SemaphoreSlim(0, 1); var result = new ConcurrentQueue <string>(); var job = new ParallelJob(new ConsoleLogProvider()) .AddTask("a", () => { result.Enqueue("a1"); lockAStart.Wait(); result.Enqueue("a2"); lockAFinished.Release(); }) .AddTask("b", () => { result.Enqueue("b"); lockBFinished.Release(); }) .AddTask("c", () => result.Enqueue("c"), new[] { "a" }); var cancellationTokenSource = new CancellationTokenSource(); var task = Task.Run(() => job.RunAllTasks(0, cancellationTokenSource.Token)); lockBFinished.Wait(); // Wait for "b" to finish. cancellationTokenSource.Cancel(); var e = TestUtility.ShouldFail <AggregateException>(() => task.Wait()); Assert.IsTrue(e.InnerException is OperationCanceledException); // only b completes immediately after cancellation Assert.AreEqual("a1b", string.Concat(result)); lockAStart.Release(); // Allow "a" to run now. // a should complete also, since it has been started prior to cancellation lockAFinished.Wait(); // Wait for "a" to finish. Assert.AreEqual("a1ba2", string.Concat(result)); }