Действие C # против события против производительности очереди - PullRequest
0 голосов
/ 15 июля 2010

У меня есть класс Camera, который создает очень большие изображения с высоким FPS, которые требуют обработки классом ImageProcessor.У меня также есть элемент управления WPF, мой вид, который отображает эту информацию.Мне нужно, чтобы каждый из этих компонентов работал в своем собственном потоке, чтобы он не блокировал обработку.

Метод 1) Камера имеет Action<Image> ImageCreated, на который подписывается ImageProcessor.ImageProcessor имеет Action<Image, Foo> ImageCreated, который содержит измененные результаты Image и Foo для отображения в представлении.

Метод 2) Камера имеет потокобезопасный (с использованием блокировок и мониторов) ProducerConsumer, для которого она создает изображения, а ImageProcessor ожидает иПотребляет.Та же история для View.

Метод 2 хорош, потому что я могу создавать и управлять своими собственными потоками.

Метод 1 хорош, потому что у меня есть несколько ImageProcessor, подписанных на класс Camera.Но я не уверен, кто-нить выполняет тяжелую работу, или если Action тратит время на создание потоков.Опять же, эти изображения появляются много раз в секунду.

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

Мысли

Ответы [ 2 ]

3 голосов
/ 15 июля 2010

Если вы не делаете это самостоятельно, использование Метода 1) не вводит многопоточность. Вызов действия (если вы не вызываете BeginInvoke) делает это синхронно, как и любой обычный вызов метода.

Я бы защищал метод 2). Нет необходимости привязывать его к одному потребителю. Если вы используете эту очередь в качестве единой точки контакта между камерами X и процессорами Y, вы отсоедините камеры от процессоров и сможете независимо изменять значения X и Y.

EDIT

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

ProcessQueue

Суть в том, что вы предоставляете очереди делегата, который может обработать один элемент - в вашем случае, Image - в конструкторе, а затем вызовите Start. Когда элементы добавляются в очередь с помощью Enqueue, они автоматически отправляются в соответствующий поток и обрабатываются.

Например, если вы хотите, чтобы изображение двигалось Camera-> Processor-> Writer (и имело переменное число каждого), то я бы сделал что-то вроде этого:

ProcessQueue<Foo> processorQueue = new ProcessQueue<Foo>(f => WriteFoo(f));
ProcessQueue<Image> cameraQueue = new ProcessQueue<Image>(i => processorQueue.Enqueue(ProcessImage(i)));

Вы можете изменить число потоков в cameraQueue (который контролирует обработку изображений) и processorQueue (который контролирует запись на диск), используя SetThreadCount.

Как только вы это сделаете, вы просто позвоните cameraQueue.Enqueue(image), когда камера сделает снимок.

1 голос
/ 15 июля 2010

Первый метод не будет работать - Action<T> будет выполняться в потоке, который его вызвал.Хотя вам, вероятно, следует использовать события вместо простых делегатов в подобных сценариях.

Второй способ - это путь, но если это возможно, вы должны использовать новую потокобезопасную коллекцию .NET4.0 вместо того, чтобы выполнять синхронизацию самостоятельно - мы все знаем, как трудно получить правильный даже самый простой многопоточный код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...