如何在c#中控制事件触发

本文关键字:事件 控制 | 更新日期: 2023-09-27 18:09:55

我写了一个程序,对通过网络摄像头传送的图像进行一些处理。每当从相机接收到新帧时,都会触发一个事件。然而,这种情况发生的频率比我希望的要高,以至于我的图像处理函数在出现新事件并再次调用相同的函数之前没有完成。

如何控制事件何时触发?我是否可以改为每5个事件执行一次图像处理?我相信我已经弄清楚了伪代码,但我更愿意看到c#中的一些示例。

如何在c#中控制事件触发

将事件回调设置为" protected ",如下所示。这样它就不会在同一时间进行多次处理。

private bool m_active;
void YourCallback(object sender, EventArgs args) 
{
  if(!m_active) 
  {
    try 
    { 
      m_active = true;
      // Do the work here... 
    }
    finally { m_active = false; }
  }
}
如果使用f.i.信号量,线程是安全的。
private System.Threading.Semaphore m_Semaphore = new System.Threading.Semaphore(0, 1);
void YourCallback(object sender, EventArgs args) 
{
  if(m_Semaphore.WaitOne(0)) 
  {
    try 
    { 
      // Do the work here... 
    }
    finally { m_Semaphore.Release(); }
  }
}

你可以使用IObservable。当图像处理正在进行时,跳过到达处理程序的事件。

这个问题有一个类似的问题:

过滤触摸。使用随时间变化的任意布尔条件的framerereportiobservable

那么你得到的伪代码是什么?我想把它翻译成c#。: -)

您可以使用DateTime变量,在其中存储事件的最后一次发生,如果不到所需的时间,则跳过事件。

如果你想让它每秒工作一次,不管它被触发了多少次:

private DateTime _lastEvent = DateTime.Now;
public void Event()
{
    if (_lastEvent + new TimeSpan(0, 0, 1) > DateTime.Now)
        return;
    _lastEvent = DateTime.Now;
    // Now do your event
    Console.WriteLine("Tick! " + _lastEvent);
}

假设您正在使用类似于:

public MyObject()
{    
   MyImageObject.Update += new UpdateEventHandler(ImageDataUpdated); 
}
private void ImageDataUpdated(object sender, EventArgs e) 
{
    // do stuff
}

您可以在事件处理程序的开头分离事件,然后使用计时器在一定时间间隔后重新附加。这将为您提供更新速率的某种精确控制。比如:

public MyObject()
{    
   MyTimer = new System.Timers.Timer(100); // 10 Hz
   MyTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
   MyTimer.Enabled = true;
}
private void ImageDataUpdated(object sender, EventArgs e) 
{
   // detach from the event to keep it from fireing until the timer event has fired.
   MyImageObject.Update -= new UpdateEventHandler(ImageDataUpdated);
    // do stuff
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
    // (re-)attach to the event handler.
   MyImageObject.Update += new UpdateEventHandler(ImageDataUpdated); 
}

使用此策略有一个很好的改变,即在事件处理程序分离时,您可以防止底层图像对象执行额外的工作(当然,这取决于图像对象的实现)。您可能会为自己的图像处理节省cpu周期。