public static void SafePost <TIn>(this ITargetBlock <TIn> target, TIn item, int interval = 200, int retryCount = 3)
        {
            bool posted = target.Post(item);

            if (posted)
            {
                return;
            }

            if (target.Completion.IsCompleted)
            {
                string msg = string.Format(
                    "Safe post to {0} failed as the block is {1}",
                    Utils.GetFriendlyName(target.GetType()),
                    target.Completion.Status);

                throw new PostToBlockFailedException(msg);
            }

            for (int i = 1; i <= retryCount; i++)
            {
                Thread.Sleep(interval * i);
                posted = target.Post(item);
                if (posted)
                {
                    return;
                }
            }

            throw new PostToBlockFailedException(
                      string.Format("Safe post to {0} failed after {1} retries", Utils.GetFriendlyName(target.GetType()), retryCount));
        }
예제 #2
0
        internal static bool TestBoundingTarget <TInput, TOutput>(ITargetBlock <TInput> target, bool greedy)
        {
            Console.WriteLine("* TestBoundingTarget {0} ({1})", target.GetType().Name, greedy ? "greedy" : "non-greedy");

            bool passed      = true;
            bool localPassed = true;
            int  i;
            var  send1 = new Task <bool> [BOUNDED_CAPACITY];
            var  send2 = new Task <bool> [BOUNDED_CAPACITY];

            if (target is ActionBlock <TInput> )
            {
                _m_pause = new ManualResetEventSlim();
            }

            // Send messages up to the bounding capacity
            for (i = 0; localPassed && i < BOUNDED_CAPACITY; i++)
            {
                // All should be accepted immediately in greedy mode
                send1[i] = target.SendAsync(default(TInput));
                if (greedy)
                {
                    localPassed = send1[i].Wait(0) && send1[i].Result;
                }
            }

            // In non-greedy mode, all should be accepted afterwards
            if (!greedy)
            {
                localPassed = Task.WaitAll(send1, COMPLETE_TIMEOUT);
            }
            passed &= localPassed;
            Assert.True(localPassed, string.Format("FAILED to send up to capacity ({0}) at iteration {1}", BOUNDED_CAPACITY, i));

            // Send one more message - it should be postponed (not consumed)
            send2[0]    = target.SendAsync(default(TInput));
            localPassed = !send2[0].Wait(NOT_COMPLETED_TIMEOUT) || target is BroadcastBlock <TInput>; // TODO: How to make BroadcastBlock reliably postpone messages?
            passed     &= localPassed;
            Assert.True(localPassed, "FAILED to postpone the excess message");

            // Unblock at least one message
            if (target is ActionBlock <TInput> )
            {
                _m_pause.Set();
            }
            else
            {
                TOutput item;
                ((IReceivableSourceBlock <TOutput>)target).TryReceive(out item);
            }

            // Now the excess item should be consumed in greedy mode and postponed in non-greedy mode
            localPassed = send2[0].Wait(greedy ? COMPLETE_TIMEOUT : NOT_COMPLETED_TIMEOUT);
            if (!greedy)
            {
                localPassed = !localPassed;
            }
            passed &= localPassed;
            Assert.True(localPassed, "FAILED to consume the excess message after unblocking");

            if (target is BatchBlock <TInput> )
            {
                // Let the task that consumed the excess message go away
                if (greedy)
                {
                    Task.Delay(COMPLETE_TIMEOUT).Wait();
                }

                // Send messages up to the bounding capacity
                for (i = 1; localPassed && i < BOUNDED_CAPACITY; i++)
                {
                    // All should be accepted immediately in greedy mode
                    send2[i] = target.SendAsync(default(TInput));
                    if (greedy)
                    {
                        localPassed = send2[i].Wait(0) && send2[i].Result;
                    }
                }

                // In non-greedy mode, all should be accepted afterwards
                if (!greedy)
                {
                    localPassed = Task.WaitAll(send2, COMPLETE_TIMEOUT);
                }
                passed &= localPassed;
                Assert.True(localPassed, string.Format("FAILED to send up to capacity ({0}) at iteration {1} AFTER unblocking", BOUNDED_CAPACITY, i));
            }

            return(passed);
        }
예제 #3
0
 public IDisposable LinkTo(ITargetBlock <TOut> target, DataflowLinkOptions linkOptions)
 {
     target = new TargetHookDelegate <TOut>(Name + " -> " + target.GetType().Name, this, target, _sync);
     return(_local.LinkTo(target));
 }
        public static void SafePost <TIn>(this ITargetBlock <TIn> target, TIn item, int interval = 200, int retryCount = 3)
        {
            bool posted = target.Post(item);

            if (posted)
            {
                return;
            }

            for (int i = 1; i <= retryCount; i++)
            {
                Thread.Sleep(interval * i);
                posted = target.Post(item);
                if (posted)
                {
                    return;
                }
            }

            throw new PostToBlockFailedException("Safe post to " + Utils.GetFriendlyName(target.GetType()) + " failed");
        }