我有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)。可以想象,我可以在一个循环中运行回调体;但是,如果可以通过添加线程(最好是任务)来加快速度,那就太好了。
循环是清空队列的最佳方法吗?或者,有没有办法同时做到这一点?
答案 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();
}