Best practice to limit event queue - c#

I am looking for advice and help regarding a specific use case of an application.
Here's the use case:
A user our our WPF application goes crazy and starts clicking all over, triggering a number of events before the first (or previous) event(s) have to finish.
Currently, WPF queues any and all clicks and queues them for sequential execution. Ideally we would like to queue up to 3 events and drop and disregard any and all clicks (user interactions) after the first 3.
What would be the best approach to solving this issue, what is the best practice for this use case. Any documentation, code and/or help would be much appreciated.

Since this really is a windows issue and not specifically a WPF issue, the only thing I can think of is hooking the message queue and discarding clicks within a certain time unless you write specific handlers into each control. The other option is to write the application such that feedback is provided to the user during an operation and input is disabled.
What does WPF use to capture mouse and keyboard input?

If you'd use MVVM all UI actions are bound to ViewModel commands or properties. In the ViewModel you'd have full control over how many and how frequently you want to process what comes from the UI. It will probably involve some sort of producer consumer queue.
Also if your user actions block the UI, you need to process them outside the UI thread as much as possible.

Related

Can windows eventtriggers be used for trivial events?

In an application I am making, I want to know when a user copies a file or clicks the start button. Those actions would be considered too trivial but they carry some importance in my application.
Yesterday, I received a comment Getting notified of any action taken by user on windows on a similar question so I am hesitating to switch the entire auditing infrastructure.
Going as per explanation of eventtriggers http://technet.microsoft.com/en-us/library/bb490901.aspx
Creates a new event trigger that monitors and acts upon the occurrence
of log events of given criteria.
I am not sure what the limits of eventtriggers and how it can help me achieve my goal without so much overhead. Can eventtriggers help me set a trigger that notifies me when the start button is clicked?.
Not possible, to my knowledge, unless you poll to find out the status. This example was already brought up in a previous question on SO:
How can I detect when the Windows 7 start menu opens
Theoretically you could write something that lives on a different thread that queries the start menu at given intervals. Then, if the start menu was detected as open you could trigger the code you want done. Just a thought...

Updating Dialog Form while downloading

Sorry if the title is a bit nondescript, I couldn't really word it right.
Basically, what I have is the following scenario:
I have a user-interface (WinForm) that allows users to pick multiple files to download, and then hit the "Download" button to commence downloading. All the downloads are processed asynchronously to avoid locking the form. However, while I don't want the form to lock up with a "Not Responding" message, I also don't want the user to be able to modify form fields while the download is running.
Ideally, I wanted to spawn a modal dialog which let's the user know the state of the download (i.e similar to firefox, except with a modal dialog). This kills 2 birds with one stone as it allows the user to get a good view of the download progress, while also stopping the user interacting with the parent form while the dialog is active.
However, to properly give the user an idea of the download progress I'd need to update the dialog during runtime. This is where I've hit a wall. My current idea is to expose some public methods of my dialog class to send it updates when files complete, and call them from within the background download thread (with proper delegates to update controls, etc)
I'm pretty sure this would work as I want, but I was just wondering if there are any more elegant solutions to this problem. Don't feel limited to the dialog approach, I'm open to all approaches that may offer a better alternative.
Cheers,
J
Alternative 1
You may consider using a BackgroundWorker, it will take of setting a new thread to do the job and provides an event based mechanism to report progress and also a method to request to cancel the operation (it is up to you if you want to use that).
To set the task for your BackgroundWorker you will need to attach a handler to the event DoWork and then call RunWorkerAsync().
Alternative 2
Another alternative is to use IObservable<T> to create a mechanism to respond to the progress of the download, then you could do the binding with using Reactive.
I take you are new to Reactive. In that case, this is best introduction available (in my opinion):
http://channel9.msdn.com/Blogs/codefest/DC2010T0100-Keynote-Rx-curing-your-asynchronous-programming-blues
If you had the freedom to not disable the UI... You could have the progress reported at a status bar, or dedicate a secondary form (which you could let the user close and get back with a NotifyIcon) where you have the current and any pending works.

Opinion on User Experience - C# Winforms

I’ve got a process which will take a little under 5 seconds to complete. The user will most likely notice the program flicker for a few seconds after pushing the “go” button.
My question is:
Is this something that would normally be dumped onto a background worker, or is there another .NET method for handling small tasks, or is this something that shouldn’t be a concern?
FYI:
The process opens a user specified excel file, processes an unknown number of lines (max 1.5 million due to excel I believe), and queries a database (very quick query). So at the worst case scenario the user uploads a 1.5 million row excel file and is running on a very slow internet connection.
If you don't want the user to be able to do anything while the file is being uploaded, then you don't need to put it on a different thread.
If you want the user to be able to go on to other tasks while the file is uploading, put it on a different thread.
As a general rule of thumb, if I have a situation where I absolutely don't want the user to do anything while a long-running process is going, I disable the controls on the form until the task is complete, and usually use a status indicator to show that progress is happening.
My personal guideline for whether or not to allow user interaction is if the results of a process could be altered by a user action in mid-stream.
For example, one program that we have parses a bunch of queries on a highly normalized database (normalized to the point where reporting is sloooow) into "reportable" tables, and I don't want the user altering data in one of the source tables while the query is running, because it will give goofy results.
If there is no harm in allowing user interaction while the process is occuring, then put it in another thread.
Edit
Actually, on reading #UrbanEsc and #archer's comments, I agree with them. Still put it on a different thread and freeze the controls (and include a progress indicator where possible).
I would push this to a background worker. Doing so will keep the UI responsive. If the process ever does lag for more than a few seconds, users start getting nervous ...especially when the lagging process causes the UI to be 'frozen'.
From a user experience point of view it might be best to hand the job over to a different thread or an asynchronous worker and tell the user that his request is being processed in the background. Once the worker finishes, a success/failure message can be handled and shown to the user as required.
The cheapest way to handle the problem is to turn the cursor into an hourglass during the processing. That tells user please wait, I'm busy.
According to the budget (time and/or effort) you're willing to throw in it, using a backgroundworker and some reporting GUI is certainly a plus. But it's up to you according to your app.
For example, I'm currently modifying an in-house app that has 3 users. In that case, the hourglass is OK: All 3 of them will quickly learn they just have to wait. Don't get me wrong: this app is damn important. Without it, the small company that uses it would just die. But if I ask them for 2 hours of extra budget for a nice and tested little GUI, background thread, blah vs an hourglass, what do you think they'll say?
On the other hand, if it's an important operation in your flagship product, of course be nice to your users! Don't hesitate: background thread. Especially if the operation may actually take much longer than those 5 seconds.
Conclusion: Be pragmatic!
I would put it into a background worker or fire of a task if you are in .NET 4.0, for example:
void OnButtonClick(...)
{
new TaskFactory().StartNew(() => { /* your excel and query code */ });
}
I'll vote for the background worker process, since a frozen UI is like a frozen application, and most of users will think your application isn't doing anything at all.
UI thread for a progress bar or some animation, info text noticing what's going on + background worker thread = win
I think every process not related with the UI itself should be started as a separate thred or, in this case, as a bg worker. This will help to maintain the app healthy and easy to improve/fix in the future.
Also, as a user or tester, I really hate flicking and freezing windows...
Regards.
A general rule of thumb is any operation that takes a second or longer to complete requires some form of feedback to the user. This can be a progress bar, message, etc. Anything longer then that then the user becomes frustrated (not sure if they did something wrong, hate waiting, etc).
For operations like this that can take longer based on the environment (number of apps, available memory, data size, hard drive speed, etc) they should ALWAYS be put on a background thread and pipe messages back to the UI. I love the BackGroundWorker for this.

Use the UI thread of a WPF application to do a long processing task on a UI element, but also update a progress bar on the same window

My program consists of a large graphing UI control that I need to spend about 15 seconds re-loading every once in a while. Because the updating code works primarily with the UI control (maybe 90% of it actually sets properties on the control), it would make sense to me to actually let the UI thread handle that. I really don't want the control to visually re-paint while it is loading in a separate thread from the UI.
I also want a progress bar to update as well that lives in the status bar of the same application window. Is there a way to break the rule in this case and re-paint only the progress bar, or should I just open a new application window for the progress bar to live in?
What would you do in this particular case?
If you can break your primary task (ie. updating the graph) in many steps, you can perform each step as a separate dispatcher message. This will allow other messages to be processed, including giving you the ability to update progress information.
The basic pattern is:
Invoke your primary task, passing in zero for the step.
Perform the step.
If there are more steps, queue another message, passing in step + 1.
You can then add in progress updates at the appropriate points in your code.
PS. Not saying this is your best option - hard to tell without knowing all the details. But this is an option.
It is not really true that there is only one UI thread in an application, it is just that most windows applications only ever create UI objects in one thread so this thread becomes "the" UI thread in the application. It is easy to understand why - this makes the code simpler to understand, and protects us from implicit thread binding issues between controls.
This suggests a possible idea, should it prove impossible to improve the speed of updating the control (which is what I would suggest to do first). Create the UI control on a separate thread. You need to make sure that the thread is suitable for UI, that is to say the threading model is STA, and that it will pump messages and not die before the control is destroyed. I don't know if you need to create the parent window in the UI thread as well, or just the control but it may be worth experimenting here.
Find a graphing UI control that is more efficient. Unless the UI thread yields to the message loop any other updates won't happen (and it will slow down your graph control's updates).
I would suggest using a progressbar in a new window (without the form headers). Make it paint the progress bar by reading the shared properties of a graph control. this way you can avoid the thread blocking (sluggish loading).. And it gives you good visual experience (progressive painting on both the controls).

Is there a way for one .NET Control to contain another Control which is owned by a seperate GUI thread?

I'm looking at creating a tabbed interface which has user controls (possibly written by plug-in developers) within a tabbed or MDI interface. These plug-in controls could unintentionally freeze their GUI thread, and I'd prefer that they not influence user controls in other tabs. Much like Google Chrome creates a process for each tab; but in this case, just threads.
Or perhaps even an MDI interface where the child MDI forms are owned by separate threads?
I've found that while I can run multiple GUI threads at once, the Form level is where they MUST be separated. Any workarounds/ideas?
For those saying this shouldn't be needed, I call bullshit. Google's Chrome browser runs tabs in separate processes for security and UI reasons. I'm merely trying to duplicate this behavior. When the people writing the user controls are sucky plug-in developers, this is important.
No it is not possible to do this in the way you are describing. A control which is owned / affinitized to another GUI thread cannot be directly contained within a control which is owned / affinitized to a different thread in such a way that it's paint function runs on the other thread.
The right way to fix this situation is to write UserControls that don't perform long-running tasks on the UI thread. If the control is blocking and waiting on some computational task, fix that. Make that task run in the background, and have the control display some non-compute-intensive content until it's done. If that task freezes, the control will be frozen in its "I'm waiting..." state, but it won't intrude on the rest of the UI.
If you're using a third-party control that you can't fix, well, in the immortal words of Jay-Z, I feel bad for you, son.
For the most part, controls shouldn't be performing any processing. Their purpose is to provide interactivity between the user and the application. For example, it is not the job of a button to fetch data from a database and present it to the user. That being said, hopefully you are doing your processing in a controls event handler, such as the Click event on the Button control. In your event handler, you can prevent the UI from appearing "hung" by processing tasks in a background thread. The BackgroundWorker is often useful in these situations.
I suggest reading up on Threading. The Microsoft® .NET Framework Application Development Foundation book has a section on threading (even if no other certification books are read, I at least recommend all .NET developers read this book). Just remember not to update the UI from a child thread. Read an example on how to make a thread-safe call to Windows controls if you're not familiar with this approach.
Instead of having or owning different GUI threads, you should view the whole issue from a different angle. Why would you want a thread associated to tab's child control to be freezed? If it does freeze and everything else feezes too, threading aside, that's not done right from ground up.
What JaredPar pointed out is correct, but that doesn't mean you cannot achieve what you want. I assume you want stuff running within a tab to continue running/stopping without affecting other controls and user-experience.
I've done it before in a complex WinForm app. Here are some readings which might give you more insights:
Threading out tasks in a C#.NET GUI
Thread and GUI
Updating GUI from Other Threads in C#
Advanced Techniques To Avoid And Detect Deadlocks In .NET Apps

Categories

Resources