Как вы контролируете запуск событий в C #? - PullRequest
2 голосов
/ 29 сентября 2011

Я написал программу, которая выполняет некоторую обработку изображения, полученного через веб-камеру.Существует событие, которое срабатывает при получении нового кадра с камеры.Однако это происходит чаще, чем хотелось бы - настолько часто, что моя функция обработки изображений не завершается до появления нового события и снова вызывает ту же функцию.

Как я могу контролировать, когда происходит событие?Могу ли я выполнять обработку изображений, скажем, каждые 5 событий?Я считаю, что у меня есть псевдокод, но я бы предпочел увидеть некоторые примеры в C #.

Ответы [ 4 ]

2 голосов
/ 29 сентября 2011

Поместите обратный вызов события «охраняется» следующим образом.Тогда он не будет выполнять обработку много раз одновременно.

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

РЕДАКТИРОВАТЬ: Потоковая безопасность при использовании fi Семафор .

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(); }
  }
}
0 голосов
/ 29 сентября 2011

Вы можете использовать IObservable.SkipWhile , чтобы пропустить событие, достигающее вашего обработчика во время обработки изображения.

В этом вопросе есть похожая проблема:

Фильтрация объекта Touch.FrameReported IObservable с использованием произвольного логического условия, которое изменяется со временем

0 голосов
/ 29 сентября 2011

Предположим, что вы присоединяетесь к событию, используя что-то похожее на:

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

При использовании этой стратегии есть хорошее изменение, заключающееся в том, что вы запрещаете базовому объекту изображения выполнять дополнительную работу, пока обработчик события отсоединен (конечно, это зависит от реализации объекта изображения). Скорее всего, вы сохраняете циклы процессора для собственной обработки изображений.

0 голосов
/ 29 сентября 2011

Тогда какой у вас код псевдо? Я хотел бы перевести его на 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...