你如何控制C#中的事件触发?

时间:2011-09-28 22:08:48

标签: c# events

我写了一个程序,对通过网络摄像头传送的图像进行一些处理。每当从相机接收到新帧时,都会触发事件。然而,这种情况发生的次数比我想象的要频繁 - 我的图像处理功能经常在新事件出现之前完成并再次调用相同的功能。

如何控制事件何时触发?我可以执行我的图像处理,比如每5个事件吗?我相信我已经找到了伪代码,但我更愿意在C#中看到一些例子。

4 个答案:

答案 0 :(得分:2)

将事件回调“保护”如下。然后它不会同时进行多次处理。

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,则线程安全。 Semaphore

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(); }
  }
}

答案 1 :(得分:0)

您可以使用IObservable.SkipWhile跳过在图像处理过程中到达处理程序的事件。

这个问题有类似的问题:

Filtering a Touch.FrameReported IObservable using arbitrary boolean condition that changes over time

答案 2 :(得分:-1)

然后你得到的伪代码是什么?我很乐意把它翻译成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);
}

答案 3 :(得分:-2)

假设您使用类似于:

的内容附加到事件
public MyObject()
{    
   MyImageObject.Update += new UpdateEventHandler(ImageDataUpdated); 
}

private void ImageDataUpdated(object sender, EventArgs e) 
{
    // do stuff
}

您可以在事件处理程序的开头分离事件,然后在一定的时间间隔后使用timer重新附加。这样可以让您对更新速率进行一定程度的精确控制。类似的东西:

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周期。