我不确定如何对代码中的事件做出两种可能的反应。我主要担心哪一种需要更少的资源。
我有一个方法,其中注册了一个观察者到一个eventproducer
。如果eventproducer
返回了什么,该方法将退出,并且方法的调用者将再次启动该方法(可以将其视为一种长轮询)。
eventproducer
有时会每秒触发很多事件,有时则会休息几分钟。
第一种方法是等待500ms的延迟,然后检查是否有返回内容,如果没有,则在500ms的延迟之后再次检查(直到5分钟的超时时间)。
eventProducer.RegisterListener((events)=>{evList.Add(events)});
while(evList.Count=0 && !TimeOut){
await Task.Delay(500);}
eventProducer.UnRegister(...);
// return evList, method gets recalled immediately
第二种方法是使用 CancellationToken
。如果 eventproducer
产生了一些东西,CancellationTokenSource
将取消源。在该方法中,我等待 Task.Delay(5min, cancellationToken)
。eventProducer.RegisterListener((events)=>{evList.Add(events);
cancelSource.Cancel();}
try
{
await Task.Delay(5min, cancellationToken)
}
catch(TaskCanceledException){//nothing to do};
eventProducer.UnRegister(...);
// return evList, method gets recalled immediately
第二种方法的优点是,如果生产者生成了东西,该方法会立即返回,我们不需要在循环中等待和唤醒。但是,使用第二种方法时,每当生产者生成内容时,都会抛出一个TaskCanceledException异常。我担心这可能会比每500毫秒唤醒和等待的负载更大,特别是在事件生产者生成大量事件时。我是否高估了抛出和捕获异常的成本?是否有一种方法可以使用CancellationToken取消Task.Delay而不抛出TaskCanceledException异常?例如,类似于task.setComplete的东西?