private void SignalAndCheck()
        {
            if (IsDisposed || _countdown == null)
            {
                return;
            }
            Monitor.Enter(_countdown);

            bool completed;

            try
            {
                if (IsDisposed || _countdown == null)
                {
                    return;
                }
                _countdown.Signal();
            }
            finally
            {
                completed = _countdown is null or {
                    CurrentCount : < 2
                };
            }

            if (completed)
            {
                OnWorkCompleted(EventArgs.Empty);
                _countdown.SignalAll();
            }

            if (_countdown != null)
            {
                Monitor.Exit(_countdown);
            }
        }
    }
Example #2
0
        private void Consume()
        {
            if (IsDisposed)
            {
                return;
            }
            OnWorkStarted(EventArgs.Empty);

            try
            {
                int    count = 0;
                T[]    items = new T[Threads];
                Task[] tasks = new Task[Threads];

                while (!IsDisposed && !Token.IsCancellationRequested && !CompleteMarked)
                {
                    if (!ReadItems(items, ref count) || count < items.Length)
                    {
                        break;
                    }

                    for (int i = 0; !IsDisposed && !Token.IsCancellationRequested && i < items.Length; i++)
                    {
                        T item = items[i];
                        ScheduledCallback?.Invoke(item);
                        _countdown.AddCount();
                        tasks[i] = TaskHelper.Run(() =>
                        {
                            try
                            {
                                Run(item);
                            }
                            finally
                            {
                                _countdown?.SignalOne();
                            }
                        }, TaskCreationOptions.PreferFairness, Token);
                    }

                    if (IsDisposed || Token.IsCancellationRequested || !tasks.WaitSilently(Token))
                    {
                        return;
                    }
                    count = 0;
                    Array.Clear(tasks, 0, tasks.Length);
                }

                if (count == items.Length)
                {
                    count = 0;
                }
                TimeSpanHelper.WasteTime(TimeSpanHelper.FAST);

                while (!IsDisposed && !Token.IsCancellationRequested)
                {
                    if (!ReadItems(items, ref count) || count < items.Length)
                    {
                        break;
                    }

                    for (int i = 0; !IsDisposed && !Token.IsCancellationRequested && i < items.Length; i++)
                    {
                        T item = items[i];
                        ScheduledCallback?.Invoke(item);
                        _countdown.AddCount();
                        tasks[i] = TaskHelper.Run(() =>
                        {
                            try
                            {
                                Run(item);
                            }
                            finally
                            {
                                _countdown?.SignalOne();
                            }
                        }, TaskCreationOptions.PreferFairness, Token);
                    }

                    if (IsDisposed || Token.IsCancellationRequested || !tasks.WaitSilently(Token))
                    {
                        return;
                    }

                    for (int i = 0; i < tasks.Length; i++)
                    {
                        ObjectHelper.Dispose(ref tasks[i]);
                    }

                    count = 0;
                    Array.Clear(tasks, 0, tasks.Length);
                }

                if (count < 1 || IsDisposed || Token.IsCancellationRequested)
                {
                    return;
                }
                Array.Resize(ref tasks, ++count);

                for (int i = 0; !IsDisposed && !Token.IsCancellationRequested && i < tasks.Length; i++)
                {
                    T item = items[i];
                    ScheduledCallback?.Invoke(item);
                    _countdown.AddCount();
                    tasks[i] = TaskHelper.Run(() =>
                    {
                        try
                        {
                            Run(item);
                        }
                        finally
                        {
                            _countdown?.SignalOne();
                        }
                    }, TaskCreationOptions.PreferFairness, Token);
                }

                if (!tasks.WaitSilently(Token))
                {
                    return;
                }

                for (int i = 0; i < tasks.Length; i++)
                {
                    ObjectHelper.Dispose(ref tasks[i]);
                }
            }
            finally
            {
                OnWorkCompleted(EventArgs.Empty);
                _countdown.SignalAll();
            }
        }
Example #3
0
        private void Consume()
        {
            if (IsDisposed)
            {
                return;
            }
            OnWorkStarted(EventArgs.Empty);

            try
            {
                int count   = 0;
                int threads = Threads;
                if (HasThreshold)
                {
                    threads++;
                }

                Task[] tasks = new Task[threads];

                while (!IsDisposed && !Token.IsCancellationRequested && !CompleteMarked)
                {
                    count = 0;
                    if (HasThreshold)
                    {
                        tasks[count++] = Task.Delay(Threshold).ConfigureAwait();
                    }

                    while (!IsDisposed && !Token.IsCancellationRequested && !CompleteMarked && count < tasks.Length)
                    {
                        lock (SyncRoot)
                        {
                            if (_queue.IsEmpty)
                            {
                                Monitor.Wait(SyncRoot, TimeSpanHelper.FAST);
                            }
                            if (IsDisposed || Token.IsCancellationRequested || _queue.IsEmpty)
                            {
                                continue;
                            }
                        }

                        while (count < tasks.Length && !IsDisposed && !Token.IsCancellationRequested && !CompleteMarked && !_queue.IsEmpty)
                        {
                            T item;

                            lock (SyncRoot)
                            {
                                if (_queue.IsEmpty || !_queue.TryDequeue(out item))
                                {
                                    continue;
                                }
                            }

                            _countdown.AddCount();
                            tasks[count++] = TaskHelper.Run(() =>
                            {
                                try
                                {
                                    Run(item);
                                }
                                finally
                                {
                                    _countdown?.SignalOne();
                                }
                            }, TaskCreationOptions.PreferFairness, Token);
                        }
                    }

                    if (count < tasks.Length)
                    {
                        break;
                    }
                    if (IsDisposed || Token.IsCancellationRequested || !tasks.WaitSilently(Token))
                    {
                        return;
                    }

                    for (int i = 0; i < tasks.Length; i++)
                    {
                        ObjectHelper.Dispose(ref tasks[i]);
                    }

                    count = 0;
                    Array.Clear(tasks, 0, tasks.Length);
                }

                TimeSpanHelper.WasteTime(TimeSpanHelper.FAST);

                while (!IsDisposed && !Token.IsCancellationRequested && !_queue.IsEmpty)
                {
                    if (HasThreshold && count == 0)
                    {
                        tasks[count++] = Task.Delay(Threshold).ConfigureAwait();
                    }

                    while (count < tasks.Length && !IsDisposed && !Token.IsCancellationRequested && !_queue.IsEmpty)
                    {
                        T item;

                        lock (SyncRoot)
                        {
                            if (_queue.IsEmpty || !_queue.TryDequeue(out item))
                            {
                                break;
                            }
                        }

                        _countdown.AddCount();
                        tasks[count++] = TaskHelper.Run(() =>
                        {
                            try
                            {
                                Run(item);
                            }
                            finally
                            {
                                _countdown?.SignalOne();
                            }
                        }, TaskCreationOptions.PreferFairness, Token);
                    }

                    if (count < tasks.Length)
                    {
                        break;
                    }
                    if (IsDisposed || Token.IsCancellationRequested || !tasks.WaitSilently(Token))
                    {
                        return;
                    }

                    for (int i = 0; i < tasks.Length; i++)
                    {
                        ObjectHelper.Dispose(ref tasks[i]);
                    }

                    count = 0;
                    Array.Clear(tasks, 0, tasks.Length);
                }

                if (count < 1 || IsDisposed || Token.IsCancellationRequested)
                {
                    return;
                }
                Array.Resize(ref tasks, count);
                tasks.WaitSilently(Token);

                for (int i = 0; i < tasks.Length; i++)
                {
                    ObjectHelper.Dispose(ref tasks[i]);
                }
            }
            finally
            {
                OnWorkCompleted(EventArgs.Empty);
                _countdown.SignalAll();
            }
        }