Как распараллелить выполнение обработчика событий в C#
У меня есть устройство Kinect, и я разрабатываю программу с его помощью, используя C#.
Для управления устройством я использовал событие AllFramesReady для обработки информации о глубине и цвете.
Я создал обработчик событий для обработки данных, который называется EventHandler1. Я делаю много обработки внутри этого обработчика событий.
Я хотел бы сделать еще несколько вычислений внутри второго обработчика событий с именем EventHandler2.
Можно ли запустить эти 2 обработчика событий какие в основном 2 функции на параллельных, на 2 разных потоках основного процесса? Если возможно, не могли бы вы дать мне пример кода для этого?
1 ответ:
Это достаточно легко обернуть в класс; однако вам нужно объединить все обработчики событий в один обработчик событий, прежде чем подписываться на желаемое событие.
Вот быстрый и грязный класс, чтобы продемонстрировать это. Первое предоставленное событие выполняется параллельно с вызовом события, в то время как все остальные выполняются в пуле потоков по умолчанию.
class ParallelEvent<TEventArg> where TEventArg : EventArgs { private readonly EventHandler<TEventArg> _handler1; private readonly EventHandler<TEventArg>[] _moreHandlers; public ParallelEvent(EventHandler<TEventArg> handler1, params EventHandler<TEventArg>[] moreHandlers) { if (handler1 == null) throw new ArgumentNullException("handler1"); if (moreHandlers == null) throw new ArgumentNullException("moreHandlers"); _handler1 = handler1; _moreHandlers = moreHandlers; } public void Handler(Object sender, TEventArg args) { IAsyncResult[] asyncResults = new IAsyncResult[_moreHandlers.Length]; for (int i = 0; i < _moreHandlers.Length; i++) asyncResults[i] = _moreHandlers[i].BeginInvoke(sender, args, null, null); _handler1(sender, args); for (int i = 0; i < _moreHandlers.Length; i++) _moreHandlers[i].EndInvoke(asyncResults[i]); } }Теперь, чтобы использовать это, мы строим класс ParallelEvent, предоставляя ему все обработчики событий, которые мы хотим запустить параллельно. Тогда мы ... подпишитесь на событие 'test' с помощью метода обработчика класса. Наконец, мы называем событие "тестом" и просматриваем результат. Рассмотрим следующий пример:
private static event EventHandler<EventArgs> test; static void Main() { var e = new ParallelEvent<EventArgs>(Test1, Test2); test += e.Handler; test(null, EventArgs.Empty); } static void Test1(Object sender, EventArgs args) { Console.WriteLine("Start Test 1"); Thread.Sleep(100); Console.WriteLine("End Test 1"); } static void Test2(Object sender, EventArgs args) { Console.WriteLine("Start Test 2"); Thread.Sleep(100); Console.WriteLine("End Test 2"); }Как и ожидалось, программа выше запускает их параллельно, как показано на следующем выходе:
Start Test 1 Start Test 2 End Test 2 End Test 1Наконец, вы должны знать о других проблемах, связанных с многопоточным кодом. Любое общее состояние, изменяемое теперь, должно быть синхронизировано и т. д.
С небольшой работой вы могли бы адаптировать вышеупомянутый класс, чтобы выставить событие, чтобы слушатели могли подписаться и отписаться по своему желанию. Затем в методе обработчика вы извлекли бы список делегатов через Delgate.GetInvocationList (). После того, как у вас есть список делегатов, вы можете обработать их так же, как существующий метод обработчика выше.
Comments