在间隔之后从队列中读取所有项目,为每个运行任务

时间:2016-05-26 15:21:46

标签: c# multithreading

我有ConcurrentQueue。外部进程将项添加到此队列(JSON请求主体)。每一分钟,我想从队列中取出所有项目并“重新提交”每个项目。我有两种方法描述我想要做的事情;但是,我还没弄清楚如何运行Timer回调直到队列为空(见下文)。

public void InitializeRequestResubmission()
{
    _timer = new Timer(e => _ResubmitRemoteRequest(), null, TimeSpan.Zero, TimeSpan.FromMinutes(1));
}

这是回调定义。

private void _ResubmitRequest()
{
    RequestModel requestModel = null;
    if (!_service.PendingResuestQueue.TryDequeue(out requestModel)) return;
    var task = _service.RetrieveWrappedTask(requestModel);
    task.Start();   // notice use of TPL
}

如您所见,我正在使用任务并行库(TPL)。可以想象,我可以在一个循环中运行回调体;但是,如果可以通过添加线程(最好是任务)来加快速度,那就太好了。

循环是清空队列的最佳方法吗?或者,有没有办法同时做到这一点?

1 个答案:

答案 0 :(得分:0)

感谢@sstan的评论,我回过头来看看BlockingCollection文档。我相应地改变了回调体(和集合)。

该集合现在定义为:

// Default collection type is a ConcurrentQueue
public BlockingCollection<RequestModel> PendingResuestQueue { get; set; }

在回调中,我正在这样做:

RequestModel requestModel = null;

while (_service.PendingResuestQueue.TryTake(out requestModel))
{
    var task = _service.RetrieveWrappedTask(requestModel);
    task.Start();
}
我假设

TryTake(T)可能由于多种原因而失败。查看documentation,它声明:

  

如果集合为空,则此方法立即返回false。

我假设false也可以因失败而退回。如果是这样的话,那就没关系,因为我将在一分钟的时间间隔内重新执行任务。

修改

看起来似乎也可以使用GetConsumingEnumerable方法,在这里:

foreach (var request in _service.PendingResuestQueue.GetConsumingEnumerable())
{
    var task = // ...
    task.Start();
}