我需要以大约4到8毫秒的间隔将项目排入队列。
另外,我的UI图层需要以大约33毫秒的间隔从这些项目中出列,处理和显示信息(它可能以该间隔多次出列)。
我不太确定我应该使用什么时间器和队列组合来实现这一点。
我想我应该为队列使用ConcurrentQueue类,但是我应该使用什么计时器机制进行入队和出队?
更新: 我最终选择了Brian Gideon和Alberto的答案。
我没有详细介绍所有细节:
我使用以下计时器来同时使用4ms计时器和33ms计时器。 (http://www.codeproject.com/Articles/98346/Microsecond-and-Millisecond-NET-Timer)
我的4ms计时器从高速摄像机读取数据,进行少量处理并将数据排入ConcurrentQueue。
我的33ms计时器从队列中取消所有项目,对每个项目进行更多处理,并将数据发送到另一个计算某个给定间隔的滚动平均值的对象。 (队列用于管理滚动平均值。)
在CompositionTarget.Rendering事件中,我从滚动平均对象中获取值并将其绘制在我的自定义线图控件上。
我提到了用户界面的33毫秒,因为这些数据被输入到实时图表中。 33毫秒大约是30帧/秒......任何比这慢的东西都会失去一些平滑度。
我最终也使用了ConccuentQueue。效果很好。
CPU受到一点打击。我认为这是由于高性能定时器。
感谢大家的帮助。
答案 0 :(得分:1)
您可以使用一个DispatcherTimer将队列出列并将其发布到用户界面,将另一个Timer用于队列。
例如:
class Producer
{
public readonly Timer timer;
public ConcurrentQueue<int> Queue {get;private set;}
Producer()
{
timer = new Timer(Callback, null, 0, 8);
Queue = new Concurrent<int>();
}
private void Callback(object state)
{
Queue.Enqueue(123);
}
}
class Consumer
{
private readonly Producer producer;
private readonly DispatcherTimer timer;
Consumer(Producer p)
{
producer = p;
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(33);
timer.Tick += new EventHandler(dispatcherTimer_Tick);
timer.Start();
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
int value;
if(producer.Queue.TryDequeue(out value))
{
// Update your UI here
}
}
}
答案 1 :(得分:1)
这些是非常严格的时间要求。我质疑UI更新的~33ms值。用户界面不应该以人类可以感知到的速度更快地进行更新,即使这样也可能有点过分。
我要做的是使用生产者 - 消费者管道。
Producer -> Processor -> UI
在我上面的原始插图中,Producer将执行生成消息和排队的步骤。处理器将监视此队列并执行与消息无关的UI处理。处理完成后,它将生成消息,其中包含更新UI线程所需的足够信息。此管道中的每个步骤都将在指定的线程上运行。我假设你确实需要两个不同的间隔(分别为4ms和33ms)。我建议你为UI添加第3个。轮询间隔可能是:
~4ms -> ~33ms -> 500ms
我故意使用波浪号(〜)来突出显示在.NET中很难实现较低的间隔时序这一事实。您可能偶尔会达到33毫秒,但使用BCL中内置的任何计时器,任意“ticks”群体的标准差将非常高。当然,4毫秒是不可能的。
您需要尝试使用多媒体计时器或其他HPET(高性能事件计时器)机制。其中一些机制使用特殊硬件。如果你走这条路,那么你可能接近那个4ms的目标。不要指望奇迹。 CLR将从一开始就对你进行堆叠(垃圾收集)。
请参阅Jim Mischel's answer here,了解您的一些选项。
答案 2 :(得分:0)
由于您正在处理UI,因此您可以使用几个DispatcherTimer而不是经典计时器。此计时器仅用于与UI交互,因此您的队列应该能够排队/出列而没有任何问题。