首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >无法将项目入队到抽象类中使用的BlockingCollection

无法将项目入队到抽象类中使用的BlockingCollection
EN

Stack Overflow用户
提问于 2020-09-14 21:12:57
回答 1查看 34关注 0票数 0

正如标题所暗示的那样,我利用一个抽象类来创建一个可重用的基类,用于使用BlockingCollection添加和删除项。我使用生产者/消费者模式来入队和出队,抽象类是通用的,所以我可以为队列指定一个对象。

我的问题发生在我调用基类入队和出队方法时,它们似乎引用了队列的另一个实例,即当我调用出队时队列上没有项,入队TryAdd()返回true。但是,当我直接在queue实例上调用Add或Take时,它工作得很好。

有人能告诉我为什么基类入队和出队方法不能像我预期的那样工作吗?我已经尝试过查找BlockingCollections的几个用法,但看不出原因。

Program.cs

代码语言:javascript
代码运行次数:0
运行
复制
static void Main(string[] args)
{

    var processor = new Processor(1,4);

    Console.ReadKey();
}

抽象基类

代码语言:javascript
代码运行次数:0
运行
复制
public abstract class BaseProcessor<T>: IDisposable
{
    protected BlockingCollection<T> _queue;
    private CancellationTokenSource _tokenSource;
    private int _producers;
    private int _consumers;
    private List<Task> _tasks;

    public BaseProcessor(int producers, int consumers)
    {
        _queue = new BlockingCollection<T>();
        _tokenSource = new CancellationTokenSource();
        _producers = producers;
        _consumers = consumers;
        _tasks = new List<Task>();
    }

    protected void Setup()
    {
        Parallel.For(0, _producers, i =>
            _tasks.Add(Task.Factory.StartNew(() => Produce(_tokenSource.Token), _tokenSource.Token)
            .ContinueWith((task) =>
            {
                Console.WriteLine("Task {0} stopped", task.Id);
            }))
         );

        Parallel.For(0, _producers, i =>
            _tasks.Add(Task.Factory.StartNew(() => Consume(_tokenSource.Token), _tokenSource.Token)
            .ContinueWith((task) =>
            {
                Console.WriteLine("Task {0} stopped", task.Id);
            }))
         );
    }

    protected abstract void Produce(CancellationToken token);
    protected abstract void Consume(CancellationToken token);

    protected void Enqueue(T item)
    {
        try
        {
            var res = _queue.TryAdd(item, TimeSpan.FromSeconds(1));
        }
        catch (Exception ex)
        {
            Console.WriteLine("Could not add item to queue: {0}", ex);
        }
    }

    protected void Enqueue(List<T> items)
    {
        items.ForEach(o => Enqueue(o));
    }

    protected T Dequeue()
    {
        try
        {
            T item;
            while (_queue.TryTake(out item, TimeSpan.FromSeconds(1))) ;
            return item;
        }
        catch (Exception ex)
        {
            Console.WriteLine("Could not remove item to queue: {0}", ex);
            return default(T);
        }
    }


    public void Dispose()
    {
        // Cancel all tokens
        _tokenSource.Cancel();

        // Wait for all tasks complete
        Task.WaitAll(_tasks.ToArray());

        _queue.Dispose();
    }
}

抽象类实现

代码语言:javascript
代码运行次数:0
运行
复制
public class Processor: BaseProcessor<QueueItem>
{

    private int _counter;

    public Processor(int producers, int consumers): base(producers, consumers)
    {
        _counter = 0;

        Setup();
    }

    protected override void Produce(CancellationToken token)
    {
        while (!token.IsCancellationRequested)
        {

            var queueItem = new QueueItem()
            {
                Id = _counter,
                Timestamp = DateTime.Now
            };

            //Enqueue(queueItem);
            _queue.Add(queueItem);

            Console.WriteLine("Enqueued: {0}", _counter);
            _counter++;

            Thread.Sleep(3000);
        }
    }

    protected override void Consume(CancellationToken token)
    {
        while (!token.IsCancellationRequested)
        {
            var item = Dequeue();
            //var item = _queue.Take();
            Console.WriteLine("Dequeued: {0}", item.Id);                
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-09-14 21:48:17

我已经发现了原因,这是我的一些代码的实现从这个链接,我正在使用。https://www.infoworld.com/article/3090215/how-to-work-with-blockingcollection-in-c.html

while (_queue.TryTake(out item,TimeSpan.FromSeconds(1);正在转储队列中的所有项,它将一直运行,直到队列实际上为空。从教程中,我假设它是在运行时,有一些东西可以尝试和采取。

代表我盲目复制和粘贴问题

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63885068

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档