Appropriate use of C # event handlers

I am currently creating a C # application that automatically authenticates a user against certain network resources when they connect to certain wireless networks.

I am currently using the Managed Wifi API to find out when a user connects / disconnects from the wireless network. I have an event handler so that when any of these things happen, one of my methods is called to check the current state of the wireless connection.

To manage the state of the application, I have another class called "explorer" that performs the operations required to change the state of the application. For example, when the wireless card connects to the correct network, the explorer needs to change the system state from "Monitoring" to "Authentication". If the authentication succeeds, the Explorer needs to change its state to Connected. Disconnecting results in the Monitoring state again, and an authentication failure results in the Error state. These state changes (if user requests) can result in TrayIcon notifications so the user knows they are being authenticated.

My current idea involves a method used to check the current state of a wireless call using "authenticate" or "release" in the state manager. However, I'm not sure if this is an appropriate use of an event handler - should I instead set a flag or send a message through some IPC to a separate thread that will start the authentication / disconnect process?

In addition to an event handler capable of requesting a connect / disconnect, the user can also execute it via the tray icon. As a result, I need to ensure that these background operations do not block tray interaction with the user.

Only one component should be able to request a system state change at any time, so I would need to use a mutex to prevent concurrent state changes. However, as I should be in sync, the rest of these components are a bit of a mystery to me.

Any advice or literature I have to read will be pointed out. I have no formal training in C #, so I apologize if I misrepresented anything.

EDIT: Most importantly, I want to check that the event will run as a separate thread, so it won't be able to block the main UI. Also, I want to check that if I have an event handler subscribed to the event, it will process events one at a time, not in parallel (so if a user connects and disconnects before the first connection event is processed, the two state changes will not will occur simultaneously).

+3


source to share


5 answers


Any advice or literature I have to read will be pointed out. I have no formal training in C #, so I apologize if I misrepresented anything.

This explains a few things. :)
I read about streams, event handling, and creating system tray icons / interfaces.

It is important to note the following:



  • Events are processed on the same thread from which they are called. If you want the event handling to not block the GUI, you need the button to move the work to a different thread.
  • When the event fires, it passes the appropriate arguments to all the methods in its list. This is almost the same as calling one method, which in turn calls all the others (see EventFired example). The purpose of events is not to call methods, since we can already do this, this is a call to methods that may not be known when the code is compiled (the click event on a control button will not be known when the library in which the control is located, for example, is compiled). In short, if you can call a method instead of using an event, then do so.

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

  • If you want the UI not blocking work on another thread. Remember that UI elements (forms, buttons, grids, labels, etc.) can only be accessed from their host thread. Use control.Invoke method to call methods on your thread.

  • Removing the option from the interface is not a good way to prevent pavement conditions (the user triggers the connect / disconnect when it is already running), as the UI will be on a different thread and may not be synchronized (it takes time for the individual threads to synchronize). While there are many ways to solve this problem, the easiest way for someone new to streaming is to use value locking. This way .NET will make sure that only one thread can change the setting at a time. You will still have to update the UI to let the user know that the update is taking place.

Your overall design sounds fine. You can use 2-3 threads (1 for the UI (tray icon), 1 for checking new network connections, and 1 (can be combined with checking the connection) that checks the internet connection.

Hope this helps, let us know if you need more (or accept an answer).

+1


source


Alternatively, alternative ...

If I were you, and since you do start over, I would seriously consider Rx Reactive Extensions

It gives a completely fresh perspective on events and event-based programming, and helps you exactly with what you encounter (including synchronization, thread handling, event pooling, stopping, starting, etc.).



It might be a bit of a "steep curve" to learn in the beginning, but again, it might be worth it.

hope this helps,

+1


source


It seems to me that you are going to re-evaluate the project. You basically need to implement events in Commander

and subscribe to them in the main application. I.e.

If there is always one component that can make changes, and you can have more than one, using some kind of synchronization mechanism, such as the one you noted Mutex

, is a perfectly valid choice.

Hope it helps.

0


source


If you want no more than one state change to occur at any time, it is best to have event handlers for external events that you listen to in order to hold the lock while they are executing. This provides an easy way to program because you are guaranteed that the state of your application does not change under you. In this particular case, a separate thread is not required.

You need to differentiate between the current state of the application and the target state. The user defines the target state ("connected", "disconnected"). Actual condition may vary. Example: the user wants to be disconnected, but the actual state is authenticated. After completing the authentication phase, the state machine should check the target state:

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

      

Separating the actual and target states allows the user to change their mind at any time, and the state machine to the desired state.

0


source


It is difficult to give an exact answer without seeing the entire (suggested) structure of your application. But overall, yes, it's okay to use an event handler for this kind of thing, although I would probably move the actual implementation into a separate method so you can more easily run it from elsewhere.

The comment about disabling the Connect button sounds straight to me, although it is possible that you may need other forms of synchronization. However, if your application doesn't need to be multithreaded, I would avoid injecting multiple threads just for the sake of it. If you do, explore the new Tasks API that was included as part of the Parallel Tasks Library . They abstract this stuff quite a bit.

And the comment about not thinking too much about the problem is well taken too. If I were in your shoes, just starting with a new language, I wouldn't try to get architecture right from the start. Dive in and develop it with the cognitive toolbox you already have. As you research more, you will realize, "Oh shit, this is a much better way to do this." And then go and do it. Refactoring is your friend.

0


source







All Articles