示例#1
0
        public DataFlowQueue([NotNull] ProducerConsumerQueueOptions <T> options, CancellationToken token = default(CancellationToken))
            : base(options, token)
        {
            _workCompletedEventSlim = new ManualResetEventSlim(false);

            // Define the mesh.
            _queue = new BufferBlock <T>(new DataflowBlockOptions
            {
                CancellationToken = Token
            });
            _processor = new ActionBlock <T>(e =>
            {
                ScheduledCallback?.Invoke(e);
                Run(e);
            }, new ExecutionDataflowBlockOptions
            {
                MaxDegreeOfParallelism = Threads,
                CancellationToken      = Token
            });
            _link = _queue.LinkTo(_processor, new DataflowLinkOptions
            {
                PropagateCompletion = true
            });
            Task.Run(Consume).ConfigureAwait();
        }
示例#2
0
        private void Consume()
        {
            _workStartedEvent.Set();
            if (IsDisposed)
            {
                return;
            }

            try
            {
                T item;

                while (!IsDisposed && !Token.IsCancellationRequested && !CompleteMarked)
                {
                    while (!IsDisposed && !Token.IsCancellationRequested && !CompleteMarked && _queue.IsEmpty)
                    {
                        _queueEvent.WaitOne(TimeSpanHelper.FAST, Token);
                    }

                    if (IsDisposed || Token.IsCancellationRequested)
                    {
                        return;
                    }
                    if (CompleteMarked)
                    {
                        break;
                    }

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

                    ScheduledCallback?.Invoke(item);
                    Run(item);
                }

                while (!IsDisposed && !Token.IsCancellationRequested && !_queue.IsEmpty)
                {
                    // no lock here
                    if (!_queue.TryDequeue(out item))
                    {
                        continue;
                    }
                    ScheduledCallback?.Invoke(item);
                    Run(item);
                }
            }
            finally
            {
                SignalAndCheck();
            }
        }
        private void Consume()
        {
            _workStartedEvent.Set();
            if (IsDisposed)
            {
                return;
            }

            try
            {
                while (!IsDisposed && !Token.IsCancellationRequested && !CompleteMarked && !_queue.IsCompleted)
                {
                    while (!IsDisposed && !Token.IsCancellationRequested && _queue.Count > 0)
                    {
                        if (!_queue.TryTake(out T item, TimeSpanHelper.FAST, Token))
                        {
                            continue;
                        }
                        ScheduledCallback?.Invoke(item);
                        Run(item);
                    }
                }

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

                foreach (T item in _queue.GetConsumingEnumerable(Token))
                {
                    ScheduledCallback?.Invoke(item);
                    Run(item);
                }
            }
            catch (ObjectDisposedException) { }
            catch (OperationCanceledException) { }
            finally
            {
                SignalAndCheck();
            }
        }
        private void Consume()
        {
            if (IsDisposed)
            {
                return;
            }
            OnWorkStarted(EventArgs.Empty);

            Task[] tasks = new Task[Threads];
            Interlocked.Exchange(ref _running, 0);

            try
            {
                while (!IsDisposed && !Token.IsCancellationRequested && !CompleteMarked)
                {
                    T item;

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

                    int index = Array.FindIndex(tasks, e => e == null || e.IsFinished());

                    if (tasks[index] != null)
                    {
                        // reuse finished task slot
                        ObjectHelper.Dispose(ref tasks[index]);
                        tasks[index] = null;
                        Interlocked.Decrement(ref _running);
                    }

                    ScheduledCallback?.Invoke(item);
                    tasks[index] = TaskHelper.Run(() => ExecRun(item), TaskCreationOptions.PreferFairness, Token).ConfigureAwait();
                    Interlocked.Increment(ref _running);
                    // don't wait until all slots are filled
                    if (_running < Threads)
                    {
                        continue;
                    }
                    Task.WaitAny(tasks, Token);
                }

                if (Token.IsCancellationRequested)
                {
                    return;
                }
                TimeSpanHelper.WasteTime(TimeSpanHelper.FAST);

                while (!IsDisposed && !Token.IsCancellationRequested)
                {
                    T item;

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

                    int index = Array.FindIndex(tasks, e => e == null || e.IsFinished());

                    if (tasks[index] != null)
                    {
                        // reuse finished task slot
                        ObjectHelper.Dispose(ref tasks[index]);
                        tasks[index] = null;
                        Interlocked.Decrement(ref _running);
                    }

                    ScheduledCallback?.Invoke(item);
                    tasks[index] = TaskHelper.Run(() => ExecRun(item), TaskCreationOptions.PreferFairness, Token).ConfigureAwait();
                    Interlocked.Increment(ref _running);
                    // don't wait until all slots are filled
                    if (_running < Threads)
                    {
                        continue;
                    }
                    Task.WaitAny(tasks, Token);
                }

                if (_running == 0)
                {
                    return;
                }
                int firstNullIndex = Array.FindIndex(tasks, e => e == null);
                if (firstNullIndex > -1)
                {
                    Array.Resize(ref tasks, firstNullIndex + 1);
                }
                Task.WaitAll(tasks, Token);
                Interlocked.Exchange(ref _running, 0);
            }
            finally
            {
                OnWorkCompleted(EventArgs.Empty);
                _allWorkDone?.Set();
            }
        }
示例#5
0
        private void Consume()
        {
            _workStartedEvent.Set();
            if (IsDisposed)
            {
                return;
            }

            object lck = GetLock();

            try
            {
                T item;

                while (!IsDisposed && !Token.IsCancellationRequested && !CompleteMarked)
                {
                    while (!IsDisposed && !Token.IsCancellationRequested && !CompleteMarked && _queue.IsEmpty)
                    {
                        lock (lck)
                            Monitor.Wait(lck, TimeSpanHelper.FAST);
                    }

                    if (IsDisposed || Token.IsCancellationRequested)
                    {
                        return;
                    }
                    if (CompleteMarked)
                    {
                        break;
                    }

                    lock (lck)
                    {
                        if (IsDisposed || Token.IsCancellationRequested)
                        {
                            return;
                        }
                        if (CompleteMarked)
                        {
                            break;
                        }
                        if (_queue.IsEmpty || !_queue.TryDequeue(out item))
                        {
                            continue;
                        }
                    }

                    ScheduledCallback?.Invoke(item);
                    Run(item);
                }

                while (!IsDisposed && !Token.IsCancellationRequested && !_queue.IsEmpty)
                {
                    lock (lck)
                    {
                        if (IsDisposed || Token.IsCancellationRequested)
                        {
                            return;
                        }
                        if (_queue.IsEmpty || !_queue.TryDequeue(out item))
                        {
                            break;
                        }
                    }

                    ScheduledCallback?.Invoke(item);
                    Run(item);
                }
            }
            finally
            {
                SignalAndCheck();
            }
        }
示例#6
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();
            }
        }
示例#7
0
        private void Consume()
        {
            if (IsDisposed)
            {
                return;
            }
            OnWorkStarted(EventArgs.Empty);

            IList <Thread> threads = new List <Thread>(Threads);

            try
            {
                T item;

                while (!IsDisposed && !Token.IsCancellationRequested && !CompleteMarked)
                {
                    lock (SyncRoot)
                    {
                        if (_queue.IsEmpty || !_queue.TryDequeue(out item))
                        {
                            continue;
                        }
                    }
                    ScheduledCallback?.Invoke(item);

                    Thread thread = new Thread(RunThread)
                    {
                        IsBackground = IsBackground,
                        Priority     = Priority
                    };

                    if (_countdown == null)
                    {
                        _countdown = new CountdownEvent(2);
                    }
                    else
                    {
                        _countdown.AddCount();
                    }
                    thread.Start(item);
                    threads.Add(thread);
                    if (threads.Count < Threads)
                    {
                        continue;
                    }
                    _countdown.Signal();
                    _countdown.Wait(Token);
                    threads.Clear();
                    ObjectHelper.Dispose(ref _countdown);
                }

                TimeSpanHelper.WasteTime(TimeSpanHelper.FAST);

                while (!IsDisposed && !Token.IsCancellationRequested)
                {
                    lock (SyncRoot)
                    {
                        if (_queue.IsEmpty || !_queue.TryDequeue(out item))
                        {
                            break;
                        }
                    }
                    ScheduledCallback?.Invoke(item);

                    Thread thread = new Thread(RunThread)
                    {
                        IsBackground = IsBackground,
                        Priority     = Priority
                    };

                    if (_countdown == null)
                    {
                        _countdown = new CountdownEvent(2);
                    }
                    else
                    {
                        _countdown.AddCount();
                    }
                    thread.Start(item);
                    threads.Add(thread);
                    if (threads.Count < Threads)
                    {
                        continue;
                    }
                    _countdown.Signal();
                    _countdown.Wait(Token);
                    threads.Clear();
                    ObjectHelper.Dispose(ref _countdown);
                }

                if (_countdown is not {
                    CurrentCount : > 1
                })
                {
                    return;
                }
                _countdown.Signal();
                _countdown.Wait(Token);
            }