public override void Run() { // 注意:每 2 个数据为一组,每 3 组数据组成一批,所以 batchSize = 2 * 3 BatchedJoinBlock <RunModel, string> batchedJoinBlock = new BatchedJoinBlock <RunModel, string>(2 * 3); var models = this.CreateCollection(); Parallel.For(0, 10, (index) => { // 注意:并发操作下,必须 lock,否则组内的数据可能因为顺序而匹配为错误的组 lock (batchedJoinBlock) { batchedJoinBlock.Target1.Post(models[index]); batchedJoinBlock.Target2.Post($"posted as {index}"); } }); batchedJoinBlock.Complete(); // BatchedJoinBlock 每个 Target 的数据必须匹配为完整组且组的数量足够组成一次批处理时才可以触发处理逻辑 for (int index = 1; index <= 4; index++) { var result = batchedJoinBlock.Receive(); Helper.PrintLine($"第 {index} 批:元素数量={result.Item1.Count}, {result.Item2.Count}"); for (int i = 0; i < result.Item1.Count; i++) { Helper.PrintLine($"{result.Item1[i].Name} {result.Item2[i]}"); } } }
private static void DataStructure_BatchedJoinBlock() { // For demonstration, create a Func<int, int> that // returns its argument, or throws ArgumentOutOfRangeException // if the argument is less than zero. Func <int, int> DoWork = n => { if (n < 0) { throw new ArgumentOutOfRangeException(); } return(n); }; // Create a BatchedJoinBlock<int, Exception> object that holds // seven elements per batch. var batchedJoinBlock = new BatchedJoinBlock <int, Exception>(7); // Post several items to the block. foreach (int i in new int[] { 5, 6, -7, -22, 13, 55, 0 }) { try { // Post the result of the worker to the // first target of the block. batchedJoinBlock.Target1.Post(DoWork(i)); } catch (ArgumentOutOfRangeException e) { // If an error occurred, post the Exception to the // second target of the block. batchedJoinBlock.Target2.Post(e); } } // Read the results from the block. var results = batchedJoinBlock.Receive(); // Print the results to the console. // Print the results. foreach (int n in results.Item1) { Console.WriteLine(n); } // Print failures. foreach (Exception e in results.Item2) { Console.WriteLine(e.Message); } }
public static void TestSync7() { bjb.LinkTo(ab3); for (int i = 0; i < 5; i++) { bjb.Target1.Post(i); } for (int i = 5; i > 0; i--) { bjb.Target2.Post(i.ToString()); } Console.WriteLine("Finished post"); bjb.Receive(); }
static public void Run() { var bjBlock = new BatchedJoinBlock <int, int>(2); for (int i = 0; i < 10; i++) { bjBlock.Target1.Post(i); } for (int i = 0; i < 10; i++) { bjBlock.Target2.Post(i); } for (int i = 0; i < 10; i++) { Console.WriteLine(Util.TupleListToString(bjBlock.Receive())); } Console.WriteLine("Done"); }
static public void Run() { var bjBlock = new BatchedJoinBlock <int, int>(2); var delayBlock1 = MakeDelayBlock(1000); var delayBlock2 = MakeDelayBlock(1000); for (int i = 0; i < 10; i++) { delayBlock1.SendAsync(i); delayBlock2.SendAsync(i - 2 * i); // same number just negated } delayBlock1.LinkTo(bjBlock.Target1); delayBlock2.LinkTo(bjBlock.Target2); for (int i = 0; i < 10; i++) { Console.WriteLine(Util.TupleListToString(bjBlock.Receive())); } Console.WriteLine("Done"); }
public void RunBatchedJoinBlockConformanceTests() { // Test Post/Receive single block var block = new BatchedJoinBlock<int, int>(2); int iter = 10; for (int i = 0; i < iter; i++) { block.Target1.Post(i); block.Target2.Post(i); if (i % block.BatchSize == 0) { var msg = block.Receive(); Assert.False(msg.Item1.Count != msg.Item2.Count, "BatchedJoinBlock Post/Receive failed, returned arrays of differnet length"); for (int j = 0; j < msg.Item1.Count; j++) { if (msg.Item1[j] != msg.Item2[j]) { Assert.False(true, "BatchedJoinBlock Post/Receive failed, returned arrys items are different"); } } } } // Test PostAll then Receive single block block = new BatchedJoinBlock<int, int>(2); for (int i = 0; i < iter; i++) { block.Target1.Post(i); block.Target2.Post(i); } Assert.False(block.OutputCount != iter, string.Format("BatchedJoinBlock Post failed, expected, incorrect OutputCount. Expected {0} actual {1}", iter, block.OutputCount)); for (int i = 0; i < block.OutputCount; i++) { var msg = block.Receive(); if (msg.Item1.Count != msg.Item2.Count) { Assert.False(true, "BatchedJoinBlock PostAll then Receive failed, returned arrays of differnet length"); } for (int j = 0; j < msg.Item1.Count; j++) { if (msg.Item1[j] != msg.Item2[j]) { Assert.False(true, "BatchedJoinBlock PostAll then Receive failed, returned arrys items are different"); } } } //Test one target Post < patchSize msg with TryReceive block = new BatchedJoinBlock<int, int>(2); block.Target1.Post(0); Tuple<IList<int>, IList<int>> result; if (block.TryReceive(out result)) { Assert.False(true, "BatchedJoinBlock.TryReceive failed, returned true and the number of messages is less than the batch size"); } if (block.OutputCount > 0) { Assert.False(true, "BatchedJoinBlock.OutputCount failed, returned count > 0 and only one target posted a message"); } // Test handling of stragglers at end of block's life block = new BatchedJoinBlock<int, int>(2); for (int i = 0; i < 10; i++) { block.Target1.Post(i); block.Target2.Post(i); } block.Target1.Post(10); block.Target1.Complete(); block.Target2.Complete(); if (block.OutputCount != 11) { Assert.False(true, "BatchedJoinBlock last batch not generated correctly"); } for (int i = 0; i < 10; i++) block.Receive(); var lastResult = block.Receive(); if (lastResult.Item1.Count != 1 || lastResult.Item2.Count != 0) { Assert.False(true, "BatchedJoinBlock last batch contains incorrect data"); } // Test BatchedJoinBlock`2 using a precanceled token { var localPassed = true; try { var cts = new CancellationTokenSource(); cts.Cancel(); var dbo = new GroupingDataflowBlockOptions { CancellationToken = cts.Token, MaxNumberOfGroups = 1 }; var bjb = new BatchedJoinBlock<int, int>(42, dbo); Tuple<IList<int>, IList<int>> ignoredValue; IList<Tuple<IList<int>, IList<int>>> ignoredValues; localPassed &= bjb.LinkTo(new ActionBlock<Tuple<IList<int>, IList<int>>>(delegate { })) != null; localPassed &= bjb.Target1.Post(42) == false; localPassed &= bjb.Target2.Post(42) == false; localPassed &= bjb.Target1.SendAsync(42).Result == false; localPassed &= bjb.Target2.SendAsync(42).Result == false; localPassed &= bjb.TryReceiveAll(out ignoredValues) == false; localPassed &= bjb.TryReceive(out ignoredValue) == false; localPassed &= bjb.OutputCount == 0; localPassed &= bjb.Completion != null; bjb.Target1.Complete(); bjb.Target2.Complete(); } catch (Exception) { localPassed = false; } Assert.True(localPassed, "Precanceled tokens don't work correctly on BJB`2"); } // Test BatchedJoinBlock`3 using a precanceled token { var localPassed = true; try { var cts = new CancellationTokenSource(); cts.Cancel(); var dbo = new GroupingDataflowBlockOptions { CancellationToken = cts.Token, MaxNumberOfGroups = 1 }; var bjb = new BatchedJoinBlock<int, int, int>(42, dbo); Tuple<IList<int>, IList<int>, IList<int>> ignoredValue; IList<Tuple<IList<int>, IList<int>, IList<int>>> ignoredValues; localPassed &= bjb.LinkTo(new ActionBlock<Tuple<IList<int>, IList<int>, IList<int>>>(delegate { })) != null; localPassed &= bjb.Target1.Post(42) == false; localPassed &= bjb.Target2.Post(42) == false; localPassed &= bjb.Target3.Post(42) == false; localPassed &= bjb.Target1.SendAsync(42).Result == false; localPassed &= bjb.Target2.SendAsync(42).Result == false; localPassed &= bjb.Target3.SendAsync(42).Result == false; localPassed &= bjb.TryReceiveAll(out ignoredValues) == false; localPassed &= bjb.TryReceive(out ignoredValue) == false; localPassed &= bjb.OutputCount == 0; localPassed &= bjb.Completion != null; bjb.Target1.Complete(); bjb.Target2.Complete(); bjb.Target3.Complete(); } catch (Exception) { localPassed = false; } Assert.True(localPassed, "Precanceled tokens don't work correctly on BJB`3"); } // Test BatchedJoinBlock`2 completion through all targets { var localPassed = true; var batchedJoin = new BatchedJoinBlock<int, int>(99); var terminator = new ActionBlock<Tuple<IList<int>, IList<int>>>(x => { }); batchedJoin.LinkTo(terminator); batchedJoin.Target1.Post(1); batchedJoin.Target1.Complete(); batchedJoin.Target2.Complete(); localPassed = batchedJoin.Completion.Wait(2000); Assert.True(localPassed, string.Format("BatchedJoinBlock`2 completed through targets - {0}", localPassed ? "Passed" : "FAILED")); } // Test BatchedJoinBlock`3 completion through all targets { var localPassed = true; var batchedJoin = new BatchedJoinBlock<int, int, int>(99); var terminator = new ActionBlock<Tuple<IList<int>, IList<int>, IList<int>>>(x => { }); batchedJoin.LinkTo(terminator); batchedJoin.Target1.Post(1); batchedJoin.Target1.Complete(); batchedJoin.Target2.Complete(); batchedJoin.Target3.Complete(); localPassed = batchedJoin.Completion.Wait(2000); Assert.True(localPassed, string.Format("BatchedJoinBlock`3 completed through targets - {0}", localPassed ? "Passed" : "FAILED")); } // Test BatchedJoinBlock`2 completion through block { var localPassed = true; var batchedJoin = new BatchedJoinBlock<int, int>(99); var terminator = new ActionBlock<Tuple<IList<int>, IList<int>>>(x => { }); batchedJoin.LinkTo(terminator); batchedJoin.Target1.Post(1); batchedJoin.Complete(); localPassed = batchedJoin.Completion.Wait(2000); Assert.True(localPassed, string.Format("BatchedJoinBlock`2 completed through block - {0}", localPassed ? "Passed" : "FAILED")); } // Test BatchedJoinBlock`3 completion through block { var localPassed = true; var batchedJoin = new BatchedJoinBlock<int, int, int>(99); var terminator = new ActionBlock<Tuple<IList<int>, IList<int>, IList<int>>>(x => { }); batchedJoin.LinkTo(terminator); batchedJoin.Target1.Post(1); batchedJoin.Complete(); localPassed = batchedJoin.Completion.Wait(2000); Assert.True(localPassed, string.Format("BatchedJoinBlock`3 completed through block - {0}", localPassed ? "Passed" : "FAILED")); } }
public void RunBatchedJoinBlockConformanceTests() { // Test Post/Receive single block var block = new BatchedJoinBlock <int, int>(2); int iter = 10; for (int i = 0; i < iter; i++) { block.Target1.Post(i); block.Target2.Post(i); if (i % block.BatchSize == 0) { var msg = block.Receive(); Assert.False(msg.Item1.Count != msg.Item2.Count, "BatchedJoinBlock Post/Receive failed, returned arrays of differnet length"); for (int j = 0; j < msg.Item1.Count; j++) { if (msg.Item1[j] != msg.Item2[j]) { Assert.False(true, "BatchedJoinBlock Post/Receive failed, returned arrys items are different"); } } } } // Test PostAll then Receive single block block = new BatchedJoinBlock <int, int>(2); for (int i = 0; i < iter; i++) { block.Target1.Post(i); block.Target2.Post(i); } Assert.False(block.OutputCount != iter, string.Format("BatchedJoinBlock Post failed, expected, incorrect OutputCount. Expected {0} actual {1}", iter, block.OutputCount)); for (int i = 0; i < block.OutputCount; i++) { var msg = block.Receive(); if (msg.Item1.Count != msg.Item2.Count) { Assert.False(true, "BatchedJoinBlock PostAll then Receive failed, returned arrays of differnet length"); } for (int j = 0; j < msg.Item1.Count; j++) { if (msg.Item1[j] != msg.Item2[j]) { Assert.False(true, "BatchedJoinBlock PostAll then Receive failed, returned arrys items are different"); } } } //Test one target Post < patchSize msg with TryReceive block = new BatchedJoinBlock <int, int>(2); block.Target1.Post(0); Tuple <IList <int>, IList <int> > result; if (block.TryReceive(out result)) { Assert.False(true, "BatchedJoinBlock.TryReceive failed, returned true and the number of messages is less than the batch size"); } if (block.OutputCount > 0) { Assert.False(true, "BatchedJoinBlock.OutputCount failed, returned count > 0 and only one target posted a message"); } // Test handling of stragglers at end of block's life block = new BatchedJoinBlock <int, int>(2); for (int i = 0; i < 10; i++) { block.Target1.Post(i); block.Target2.Post(i); } block.Target1.Post(10); block.Target1.Complete(); block.Target2.Complete(); if (block.OutputCount != 11) { Assert.False(true, "BatchedJoinBlock last batch not generated correctly"); } for (int i = 0; i < 10; i++) { block.Receive(); } var lastResult = block.Receive(); if (lastResult.Item1.Count != 1 || lastResult.Item2.Count != 0) { Assert.False(true, "BatchedJoinBlock last batch contains incorrect data"); } // Test BatchedJoinBlock`2 using a precanceled token { var localPassed = true; try { var cts = new CancellationTokenSource(); cts.Cancel(); var dbo = new GroupingDataflowBlockOptions { CancellationToken = cts.Token, MaxNumberOfGroups = 1 }; var bjb = new BatchedJoinBlock <int, int>(42, dbo); Tuple <IList <int>, IList <int> > ignoredValue; IList <Tuple <IList <int>, IList <int> > > ignoredValues; localPassed &= bjb.LinkTo(new ActionBlock <Tuple <IList <int>, IList <int> > >(delegate { })) != null; localPassed &= bjb.Target1.Post(42) == false; localPassed &= bjb.Target2.Post(42) == false; localPassed &= bjb.Target1.SendAsync(42).Result == false; localPassed &= bjb.Target2.SendAsync(42).Result == false; localPassed &= bjb.TryReceiveAll(out ignoredValues) == false; localPassed &= bjb.TryReceive(out ignoredValue) == false; localPassed &= bjb.OutputCount == 0; localPassed &= bjb.Completion != null; bjb.Target1.Complete(); bjb.Target2.Complete(); } catch (Exception) { localPassed = false; } Assert.True(localPassed, "Precanceled tokens don't work correctly on BJB`2"); } // Test BatchedJoinBlock`3 using a precanceled token { var localPassed = true; try { var cts = new CancellationTokenSource(); cts.Cancel(); var dbo = new GroupingDataflowBlockOptions { CancellationToken = cts.Token, MaxNumberOfGroups = 1 }; var bjb = new BatchedJoinBlock <int, int, int>(42, dbo); Tuple <IList <int>, IList <int>, IList <int> > ignoredValue; IList <Tuple <IList <int>, IList <int>, IList <int> > > ignoredValues; localPassed &= bjb.LinkTo(new ActionBlock <Tuple <IList <int>, IList <int>, IList <int> > >(delegate { })) != null; localPassed &= bjb.Target1.Post(42) == false; localPassed &= bjb.Target2.Post(42) == false; localPassed &= bjb.Target3.Post(42) == false; localPassed &= bjb.Target1.SendAsync(42).Result == false; localPassed &= bjb.Target2.SendAsync(42).Result == false; localPassed &= bjb.Target3.SendAsync(42).Result == false; localPassed &= bjb.TryReceiveAll(out ignoredValues) == false; localPassed &= bjb.TryReceive(out ignoredValue) == false; localPassed &= bjb.OutputCount == 0; localPassed &= bjb.Completion != null; bjb.Target1.Complete(); bjb.Target2.Complete(); bjb.Target3.Complete(); } catch (Exception) { localPassed = false; } Assert.True(localPassed, "Precanceled tokens don't work correctly on BJB`3"); } // Test BatchedJoinBlock`2 completion through all targets { var localPassed = true; var batchedJoin = new BatchedJoinBlock <int, int>(99); var terminator = new ActionBlock <Tuple <IList <int>, IList <int> > >(x => { }); batchedJoin.LinkTo(terminator); batchedJoin.Target1.Post(1); batchedJoin.Target1.Complete(); batchedJoin.Target2.Complete(); localPassed = batchedJoin.Completion.Wait(2000); Assert.True(localPassed, string.Format("BatchedJoinBlock`2 completed through targets - {0}", localPassed ? "Passed" : "FAILED")); } // Test BatchedJoinBlock`3 completion through all targets { var localPassed = true; var batchedJoin = new BatchedJoinBlock <int, int, int>(99); var terminator = new ActionBlock <Tuple <IList <int>, IList <int>, IList <int> > >(x => { }); batchedJoin.LinkTo(terminator); batchedJoin.Target1.Post(1); batchedJoin.Target1.Complete(); batchedJoin.Target2.Complete(); batchedJoin.Target3.Complete(); localPassed = batchedJoin.Completion.Wait(2000); Assert.True(localPassed, string.Format("BatchedJoinBlock`3 completed through targets - {0}", localPassed ? "Passed" : "FAILED")); } // Test BatchedJoinBlock`2 completion through block { var localPassed = true; var batchedJoin = new BatchedJoinBlock <int, int>(99); var terminator = new ActionBlock <Tuple <IList <int>, IList <int> > >(x => { }); batchedJoin.LinkTo(terminator); batchedJoin.Target1.Post(1); batchedJoin.Complete(); localPassed = batchedJoin.Completion.Wait(2000); Assert.True(localPassed, string.Format("BatchedJoinBlock`2 completed through block - {0}", localPassed ? "Passed" : "FAILED")); } // Test BatchedJoinBlock`3 completion through block { var localPassed = true; var batchedJoin = new BatchedJoinBlock <int, int, int>(99); var terminator = new ActionBlock <Tuple <IList <int>, IList <int>, IList <int> > >(x => { }); batchedJoin.LinkTo(terminator); batchedJoin.Target1.Post(1); batchedJoin.Complete(); localPassed = batchedJoin.Completion.Wait(2000); Assert.True(localPassed, string.Format("BatchedJoinBlock`3 completed through block - {0}", localPassed ? "Passed" : "FAILED")); } }
public static void Run() { // For demonstration, create a Func<int, int> that // returns its argument, or throws ArgumentOutOfRangeException // if the argument is less than zero. Func <int, int> DoWork = n => { if (n < 0) { Console.WriteLine("DoWork.ArgumentOutOfRangeException: " + n); throw new ArgumentOutOfRangeException(); } return(n); }; // Create a BatchedJoinBlock<int, Exception> object that holds // seven elements per batch. // BatchedJoinBlock<T1,T2> Class // Provides a dataflow block that batches a specified number of inputs of // potentially differing types provided to one or more of its targets BatchedJoinBlock <int, Exception> batchedJoinBlock = new BatchedJoinBlock <int, Exception>(7); Console.WriteLine("BatchedJoinBlock<int, Exception> batchedJoinBlock = new BatchedJoinBlock<int, Exception>(7);"); // Post several items to the block. int[] ints = { 5, 6, -7, -22, 13, 55, 0 }; Console.WriteLine("int[] ints = {5, 6, -7, -22, 13, 55, 0};"); foreach (int i in ints) { try { // Post the result of the worker to the // first target of the block. Console.WriteLine("try: batchedJoinBlock.Target1.Post(DoWork({0}));", i); batchedJoinBlock.Target1.Post(DoWork(i)); } catch (ArgumentOutOfRangeException e) { // If an error occurred, post the Exception to the // second target of the block. Console.WriteLine("catch: batchedJoinBlock.Target2.Post({0});", e.Message); batchedJoinBlock.Target2.Post(e); } } // Read the results from the block. Console.WriteLine("Tuple<IList<int>, IList<Exception>> results = batchedJoinBlock.Receive();"); Tuple <IList <int>, IList <Exception> > results = batchedJoinBlock.Receive(); // Print the results to the console. // Print the results. IList <int> resultsItem1 = results.Item1; foreach (int n in resultsItem1) { Console.WriteLine("results.Item1: " + n); } // Print failures. IList <Exception> resultsItem2 = results.Item2; foreach (Exception e in resultsItem2) { Console.WriteLine("results.Item2: " + e.Message); } }