2012-04-06 4 views
3

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

В настоящее время я использую Managed Wifi API, чтобы узнать, когда пользователь подключается/отключается от беспроводной сети. У меня есть обработчик событий, так что, когда происходит какое-либо из этих действий, один из моих методов вызывается для проверки текущего состояния беспроводного соединения.

Для управления состоянием приложения у меня есть другой класс, который называется «проводником», который выполняет операции, необходимые для изменения состояния приложения. Например, когда беспроводная карта подключается к правильной сети, проводнику необходимо изменить состояние системы с «Мониторинг» на «Аутентификация». Если аутентификация завершается успешно, проводнику необходимо изменить состояние на «Подключено». Отключение приводит к состоянию «Мониторинг» снова, и ошибка аутентификации приводит к состоянию «Ошибка». Эти изменения состояния (если запросы пользователя) могут привести к уведомлениям TrayIcon, поэтому пользователь знает, что они проходят проверку подлинности.

Моя нынешняя идея включает в себя метод, используемый для проверки текущего состояния беспроводного вызова методом «аутентификации» или «разъединения» в диспетчере состояний. Однако я не уверен, что это подходящее использование обработчика событий - следует ли вместо этого устанавливать флаг или отправлять сообщение через какой-либо IPC в отдельный поток, который начнет процесс аутентификации/разъединения?

В дополнение к обработчику событий, способному запросить соединение/разъединение, пользователь может также выполнить его через значок в трее. В результате мне необходимо обеспечить, чтобы эти фоновые операции не блокировали взаимодействие лотка с пользователем.

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

Любые советы или литература, которые я должен был прочитать, были бы оценены. У меня нет формального обучения на языке C#, поэтому я прошу прощения, если я что-то исказил.

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

+1

Избегайте чрезмерного размышления об этом. Просто создайте событие и пусть ваш пользовательский интерфейс реализует его, отключив кнопку «Подключиться». Автоматическая блокировка * и * визуальная обратная связь. –

+0

Вот несколько ссылок для вас. Во-первых, чтобы синхронизировать все, сервисная шина Rhino может помочь. http://hibernatingrhinos.com/open-source/rhino-service-bus Во-вторых, вот отличный пример для потоковой передачи в .NET, начиная с основ и расширяясь до расширенных тем: http://www.yoda.arachsys.com /csharp/threads/index.shtml –

ответ

0

Для меня кажется, что вы собираетесь перестроить проект. Вам необходимо выполнить мероприятие в Commander и в главном приложении подписаться на них. То есть.

Если есть всегда один компонент, вы можете внести изменения, и у вас может быть больше одного, используя какой-либо механизм синхронизации, например, отмеченный вами Mutex, является совершенно допустимым выбором.

Надеюсь, это поможет.

0

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

Вам необходимо провести различие между текущим состоянием приложения и целевым состоянием. Пользователь определяет целевое состояние («подключено», «отключено»). Фактическое состояние может отличаться. Пример: пользователь хочет быть отключенным, но фактическое состояние аутентифицируется. После того, как этап аутентификации завершается государственная машина должна проверить целевое состояние:

targetState == connected => set current state to connected 
targetState == disconnected => begin to disconnect and set state to disconnecting 

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

0

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

Комментарий об отключении кнопки «Подключиться» звучит прямо на меня, хотя вполне возможно, что вам могут понадобиться другие формы синхронизации. Однако, если ваше приложение не должно быть многопоточным, я бы избегал вводить несколько потоков только ради него. Если вы это сделаете, загляните в новый Task API, который был включен как часть Task Parallel Library. Они довольно много абстрагируют этот материал.

И комментарий не слишком задумываясь о проблеме также хорошо взят. Если бы я был на вашем месте, только начиная с нового языка, я бы не стал пытаться получить архитектуру сразу с самого начала. Погрузитесь и разработайте его с помощью набора когнитивных инструментов, который у вас уже есть. По мере того как вы исследуете больше, вы поймете: «О, дерьмо, это гораздо лучший способ сделать это». И тогда иди и сделай так. Рефакторинг - ваш друг.

1

Любые советы или литература, которые я должен был прочитать, были бы оценены. У меня нет формального обучения на языке C#, поэтому я прошу прощения, если я что-то исказил.

Это объясняет некоторые вещи. :)
Я читал о потоках, обработке событий и создании значков/интерфейсов системного лотка.

Важно отметить следующее:

  • События обрабатываются в том же потоке они называются из. Если вы хотите, чтобы обработка события не блокировала графический интерфейс, вам необходимо, чтобы кнопка переместила работу в другой поток.
  • Когда событие запущено, он передает соответствующие аргументы всем методам в своем списке. Это почти то же самое, что и вызов одного метода, который в свою очередь вызывает все остальные (см. Пример EventFired). Цель событий - не вызывать методы, поскольку мы можем это сделать уже, это вызов методов, которые могут не быть известны при компиляции кода (событие click на кнопке управления не будет известно, когда библиотека, в которой находится элемент управления , например, компилируется). Короче говоря, если вы можете вызвать метод вместо использования события, сделайте это.

    void EventFired(int arg1, object arg2) 
    { 
        subscribedMethod1(arg1, arg2); 
        SubscribedMethod2(arg1, arg2); 
        SubscribedMethod3(arg1, arg2); 
        SubscribedMethod4(arg1, arg2); 
        SubscribedMethod5(arg1, arg2); 
        SubscribedMethod6(arg1, arg2); 
        SubscribedMethod7(arg1, arg2); 
    } 
    
  • Если вы хотите, чтобы предотвратить пользовательский интерфейс от блокировки делают работу в другом потоке. Помните, что элементы пользовательского интерфейса (формы, кнопки, сетки, метки и т. Д.) Могут быть доступны только из их хост-потока. Используйте метод control.Invoke для вызова методов в их потоке.

  • Извлечение опции из интерфейса не является хорошим способом предотвращения условий дорожного покрытия (пользователь начинает соединение/отсоединение, когда он уже запущен), поскольку пользовательский интерфейс будет находиться в другом потоке и может быть не синхронизирован (для синхронизации отдельных потоков требуется время). Хотя есть много способов решить эту проблему, проще всего для кого-то нового для потоковой передачи использовать блокировку значения. Таким образом, .NET будет следить за тем, чтобы только один поток мог изменять настройку за раз. Вам все равно придется обновлять пользовательский интерфейс, чтобы пользователь знал, что обновление происходит.

Ваш общий дизайн звучит отлично. Вы можете использовать 2-3 потока (1 для пользовательского интерфейса (значок в трее), 1 для проверки новых сетевых подключений и 1 (может быть объединен с проверкой соединения), который проверяет подключение к Интернету.

Надеюсь, дайте нам знать, если вам нужно больше (или принять ответ).

+0

«Если вы хотите, чтобы обработка события не блокировала графический интерфейс, вам необходимо, чтобы кнопка переместила произведение в другой поток». Я узнаю это, когда я построил предыдущее приложение - нажатие на кнопку запускает другой поток, который будет остановлен через bool (я знаю, что вы не хотите просто прервать другой поток). Тем не менее, событие, которое я обсуждаю ('WlanNotificationEventHandler WlanNotification'), часть' Managed Wifi Api' - какой поток будут обрабатывать методы, которые подписываются на это событие? «Основной» поток, который контролирует мой пользовательский интерфейс? Или отдельный поток? – BSchlinker

+0

@BSchlinker Я ожидаю, что он будет запущен в потоке, где вы создали экземпляр WlanClient. Самый простой способ узнать наверняка - поставить точку прерывания в первой строке метода, который подписался на это событие, запустить программу и сгенерировать событие, чтобы точка останова была удалена, откройте панель потоков (Debug \ Windows \Потоки). Если указатель находится на зеленой нити, то вы работаете в основном потоке. Если он находится на желтой нити, вы работаете на рабочем потоке. – Trisped

+0

Он работает на рабочем потоке, а не работает на основном потоке. Итак, кто запускает рабочий поток? Управляемый API Wifi? – BSchlinker

1

как вариант, альтернатива ...

Если бы я тебя, и так как вы начинаете заново в любом случае, я бы серьезно рассмотреть
Rx Reactive Extensions

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

Это может быть немного «крутая кривая», чтобы учиться в начале, но, возможно, это того стоит.

надеюсь, что это поможет,