Подходит ли этот дизайн потока/фонового рабочего для приложения C# WPF?

Будучи новичком в использовании потоков и т. д. в пользовательском интерфейсе, могу ли я спросить, следующий простой дизайн выглядит нормально. См. диаграмму изображение по ссылке здесь

Особенно:

а) использование backgroundworker и backgroundworker ProgressChanged, чтобы агрегатор работал в отдельном потоке. Поэтому мне понадобится собственный класс/тип, в котором будут все данные, которые мне нужно передать из потока агрегатора в поток пользовательского интерфейса, который я предполагаю.

б) создать отдельный поток в агрегаторе, чтобы гарантировать, что метод обратного вызова SharpPCap/WinPCap находится в другом потоке. Таким образом, этот поток диспетчера захвата записывает результаты пакетов в общий буфер. Я предполагаю, что если код может видеть переменную буфера, они оба могут получить к ней доступ, независимо от того, в каком потоке они работают?

Благодарность


person Greg    schedule 21.07.2010    source источник


Ответы (1)


У меня есть пара предложений:

  1. Я бы не рекомендовал использовать для этого BackgroundWorker и ProgressChanged. Учитывая, что вы хотите «опрашивать и агрегировать» каждую секунду, я бы рекомендовал просто использовать таймер (возможно, DispatcherTimer). Вы можете использовать Dispatcher.BeginInvoke для обратного маршалирования вызовов в поток пользовательского интерфейса, если он выполняется в отдельном потоке (вы также можете использовать таймер на основе потока пользовательского интерфейса, если хотите).

  2. Я бы рекомендовал вместо этого использовать ConcurrentQueue<T> для хранения данных вашего пакета. списка. Это избавит вас от необходимости блокировки вашего списка. Если вам необходимо придерживаться версий .NET ‹4, вы можете использовать List<T>, но вам потребуется синхронизировать доступ к нему (заблокировать какой-либо объект для защиты операций чтения/записи в списке). Оба потока смогут использовать одну и ту же коллекцию при условии, что она потокобезопасна или правильно синхронизирована.

person Reed Copsey    schedule 21.07.2010
comment
спасибо Re 1) нужно ли для этого агрегатору знание пользовательского интерфейса? Если бы я хотел повторно использовать его для других пользовательских интерфейсов, что бы вы порекомендовали здесь? Событийный подход как-то? - person Greg; 21.07.2010
comment
Я согласен с большинством комментариев Рида, за исключением того, что я бы рекомендовал использовать System.Timers.Timer для опроса и использовать Task, запланированный для TaskScheduler.FromCurrentSynchronizationContext, чтобы маршалировать вызовы обратно в поток пользовательского интерфейса. Преимущество этого заключается в том, что он не специфичен для WPF. - person Stephen Cleary; 21.07.2010
comment
Я все еще вполне вижу преимущество нашего Dispatcher над BackgroundWorker? Какова основная причина в моем случае, почему я должен запускать его поверх BackgroundWorker в качестве механизма для получения обновлений обратно на уровень пользовательского интерфейса? - person Greg; 21.07.2010
comment
@Greg: Использование ReportProgress в BW на самом деле не использует его по прямому назначению. Это приводит к тому, что ваш код становится неясным, а также его труднее написать, чем просто повторить свой код. Предложение Стивена по использованию TaskScheduler очень хорошее, но вам нужно убедиться, что ваш фоновый поток заранее передается планировщику, созданному в контексте пользовательского интерфейса. (Я собирался написать это изначально, но это требовало небольшого дополнительного объяснения, поэтому я его пропустил...) - person Reed Copsey; 21.07.2010
comment
@Reed - спасибо, но все еще немного запутался - не могли бы вы уточнить, возможно, с точки зрения моей опубликованной диаграммы / изображения, где вы имеете в виду запуск TaskScheduler / фонового потока и т. д. по отношению к потоку агрегатора и потоку пользовательского интерфейса, который у меня есть на моем схема? Кстати, для опроса когда-либо второго элемента я рассматривал возможность использования кварца.net, чтобы гарантировать, что временные интервалы не смещаются (не уверен, что это повлияет на ваше предложение). - person Greg; 22.07.2010
comment
@Greg: я бы сделал агрегатор таймером - и он порождал бы поток для запуска диспетчера захвата. Таймер Aggregator может использовать Dispatcher (через BeginInvoke) для взаимодействия с потоком пользовательского интерфейса. (Только что увидел ваше редактирование - я бы, наверное, не слишком беспокоился о дрейфе, если вы опрашиваете каждую секунду ....) - person Reed Copsey; 22.07.2010