LabVIEW: how to stop a loop inside event structure - loops

I create an event structure for two buttons, start ROI and stop ROI. When the user presses start ROI it goes to this event and do the following:
check if the camera is open and is in idle
enqueue "none" to the queue to initialize the queue
in the loop dequeue every iteration to find if there's invoked message, which is inserted from the callback
if the element is "invoked" then update the region
The problem I am seeing is that when it is in the loop I cannot press the stop ROI or any other buttons. But the ROI keeps updating. I am puzzled why this is happening.
Could you please help me ?
Thanks,

Edit events for that case (the one pictured in your screenshot) and make sure the box titled "Lock front panel" is unchecked. This should solve your issue.

As far as I can tell from the code you have shown, your event structure should not be attempting to handle the stop ROI Value Change event. It doesn't need to, because the only place you need to respond to that event is inside your innermost loop and there you are handling the button click by polling the value of its terminal anyway.
However as #Dave_St explains, this will only work if the loop runs regularly, i.e. if the Dequeue Element function either receives data regularly or has a short timeout, because otherwise it will wait for data indefinitely and the loop iteration will not complete until the dequeue has executed. Having an event handler for the button click can't help here because it can't interrupt the program flow - the event structure only waits for an event to happen and then allows the code in the corresponding frame to execute.
More generally though, and looking at your front panel which suggests you are going to want to deal with further controls and events, the problem is that you are trying to do a time-consuming task inside an event structure. That's not how event structures are designed to be used. You should use a design pattern for your app that separates the UI (responding to user input) from the process (acquiring images from a camera) - perhaps a queued message handler would be suitable. This may seem harder to understand at first but it will make your program much easier to develop, extend, and maintain.
You can find more information, examples and templates in your LabVIEW installation and its online help. I do recommend using one of the templates as your starting point if possible because they already implement a lot of common functionality and can save you a lot of redundant effort.

Related

Process lots of small tasks and keep the UI responsive

I have a WPF application that needs to do some processing of many small tasks.
These small tasks are all generated at the same time and added to the Dispatcher Queue with a priority of Normal. At the same time a busy indicator is being displayed. The result is that the busy indicator actually freezes despite the work being broken into tasks.
I tried changing the priority of these tasks to be Background to see if that fixed it, but still the busy indicator froze.
I subscribed to the Dispatcher.Hooks.OperationStarted event to see if any render jobs occurred while my tasks were processing but they didn't.
Any ideas what is going on?
Some technical details:
The tasks are actually just messages coming from an Observable sequence, and they are "queued" into the dispatcher by a call to ReactiveUI's ObserveOn(RxApp.MainThreadScheduler) which should be equivalent to ObserveOn(DispatcherScheduler). The work portion of each of these tasks is the code that is subscribing through the ObserveOn call e.g.
IObservable<TaskMessage> incomingTasks;
incomingTasks.ObserveOn(RxApp.MainThreadScheduler).Subscribe(SomeMethodWhichDoesWork);
in this example, incomingTasks would produce maybe 3000+ messages in short succession, the ObserveOn pushes each call to SomeMethodWhichDoesWork onto the Dispatcher queue so that it will be processed later
The basic problem
The reason you are seeing the busy indicator stall is because your SomeMethodWhichDoesWork is taking too long. While it is running, it prevents any other work from occuring on the Dispatcher.
Input and Render priority operations generated to handle animations are lower than Normal, but higher priority than Background operations. However, operations on the Dispatcher are not interrupted by the enqueing of higher priority operations. So a Render operation will have to wait for a running operation, even if it is a Background operation.
Caveat regarding observing on the DispatcherScheduler
ObserveOn(DispatcherScheduler) will push everything through at Normal priority by default. More recent versions of Rx have on overload that allows you to specify a priority.
One point to highlight that's often missed is that items will be queued onto the Dispatcher by the DispatcherScheduler as soon as they arrive NOT one after the other.
So if your 3000 items all turn up fairly close together, you will have 3000 operations at Normal priority backed up on the Dispatcher blocking everything of the same or lower priority until they are done - including Render operations. This is almost certainly what you were seeing - and that means you might still see problems even if you do all but the UI update work on a background thread depending on how heavy your UI updates are.
In addition to this, you should check you aren't running the whole subscription on the UI thread - as Lee says. I usually write my code so that I Subscribe on a background thread rather than use SubscribeOn, although this is perfectly fine too.
Recommendations
Whatever you do, do as much work as possible on a background thread. That point has been done to death on StackOverflow, and elsewhere. Here are some good resources covering this:
MSDN Entry on WPF Threading Model
MSDN Magazine "Build More Responsive Apps With The Dispatcher", by Shaun Wildermuth
If you want to keep the UI responsive in the face of lots of small updates you can either:
Schedule items at a lower priority, which is nice and easy - but not so good if you need a certain priority
Store updates in your own queue and enqueue them and have each operation you run Invoke the next item from your queue as it's last step.
The bigger picture
It's worth stepping back a bit and looking at the bigger picture as well.
If you separately dump 3000 items into the UI in succession, what's that going to do for the user? At best they are going to be running a monitor with a refresh rate of 100Hz, probably lower. I find that frame rates of 10 per second are more than adequate for most purposes.
Not only that, human beings supposedly can't handle more than 5-9 bits of information in one go - so you might find better ways of aggregating and displaying information than updating so many things at once. For example, make use of master/detail views rather than showing everything on screen at once etc. etc.
Another option is to review how much work your UI update is causing. Some controls (I'm looking at you XamDataGrid) can have very lengthy measure/arrange layout operations. Can you simplify your animations? Use a simpler Visual tree? Think about the popular busy spinner that looks like circling dots - but really it's just changing their color. A great effect that is fairly cheap to achieve. It's worth profiling your application to see where time is going.
I would think about the overrall approach front-to-back as well. If you are reasonably certain you are going to get that many items to update at once, why not buffer them up and manage them in chunks? That would might have advantages all the way back to the source - which perhaps is on a server somewhere? In any case, Rx has some nice operators, like Buffer that can turn a stream of individual items into a larger lists - and it has overloads that can buffer by time and size together.
Have you tried using .SubscribeOn(TaskPoolScheduler.TaskPool) to subscribe on a different thread?
#Pedro Pombeiro has the right answer.
The reason you are seeing the freezes on the UI is that you are queueing the work on the Dispatcher. This means the work will be done on the UI thread. You can think of the Dispatcher as a message pump that is constant draining messages from each of its queues (which you can think of each of the priorities [SystemIdle, ApplicationIdle, ContextIdle, Background, Input, Loaded, Render, DataBind, Normal, Send])
Putting you work onto a different priority queue, does not make it run concurrently, just asynchronously.
To run your work on another thread using Rx, then use SubscribeOn as above. Remember to then schedule any updates to the UI back on to the Dispatcher with ObserveOn.

WPF user interface with long processing execution hangs

I am extremely Sorry for this long post. I need some help on c# wpf issues. I have build a complicated UI(somehow) and there is some buttons... like start and stop and others.
When i click the start button a execution process starts with communicating with some protocol layer and others and it is a long process .. and during this process i have to show some notification UI like "Enter a Text", "Select Something" etc... this time i have to show some wpf window object... and after some time i have to automatically destroy the window and go with processing again.
At first i tried to run the execution in the Main window class. But it results that when the execution starts.. user can't click anything and ui doesno't respond rather just hangs. I investigate the problem... and found that UI is busy with processing in the execution on protocol layer so its not responding.
Here is my problem... can u give me some solution that...
i will have 2 button..start and stop
when i click the start button... a large process will start( like nested for loop with a large int which will continue for 50 seconds) in function named Processor.
at time of processing the function Processor will create several window and show them wait for 5-10 seconds and also destroy them. or user click;s on the window
And the whole time the stop button should be clickable so that when i click the stop button .. the process should be stop.
I tried this with backgroundworker, dispatcher... and using separate thread. but no luck. I guess i am missing something. because if i wait for some result showing a window..the window will definitely hang.. and if i separate them with different thread.. it will not communicate with each other. please give me some suggestions
Dispatcher is definitely the solution. You may need to set the Dispatcher Priority. Sharing some relevant code may also reveal some issues.
BackgroundWorker should do what you need. Set WorkerSupportsCancellation and WorkerReportsProgress to true.
I wouldn't suggest popping up multiple windows. Pop up one window to display status. In your loop in DoWork, call BackgroundWorker.ReportProgress. Then in the ProgressChanged event handler, update the status of the window.
To implement Stop:
In your DoWork method you need to check the CancellationPending property on the BackgroundWorker in your loop. When it is true you need to exit that method. On the stop button click, call BackgroundWorker.CancelAsync().

Adding controls to winform while allowing user to enter input

I have a WinForms data entry form that will have upwards of 1500 questions. I have the questions broken into sections, and each section will have an unkown number of questions. Each section is its own user control and has rows (2 panels, 2 labels, a textbox, and another user control) created and added dynamically for each question. The section controls are then added to the form.
My problem is that the process takes a lot of time, even with using TPL (Task Parallel Library). I would ultimately like to create/add the controls and allow the user to start entering data at the same time. The controls are going into a scrollable panel. While the user is entering data, that data will need processed on a local database...so more threading could be necessary.
I have tried working with TPL, which I am new to, by having all the controls added to a list during processing and then sorted and added to the form after the Parallel.ForEach was complete...takes about 20 seconds for over 1200 questions.
I also tried utilizing a BackgroundWorker component. Using the BWC seems to be the faster of the two, but there is a race condition for the ProgressChanged() eventhandler and not all controls get added...not to mention the way the form looks with all the rerendering.
Am i just using TPL wrong? What's the best way to go about this? Is there another way or do I just make the user stick out the wait?
Thanks
Am i just using TPL wrong? What's the best way to go about this? Is there another way or do I just make the user stick out the wait?
Most likely, you can use TPL, and get the same response time as BW, but a nicer API for this type of operation.
The trick here is to get a TaskScheduler setup for UI interaction, and then use the Task class to push the controls back onto the UI thread as they're ready. I have a blog post on this specific subject which shows how to get a TaskScheduler setup to use with UI threads.
However, I would recommend keeping these in memory and pushing them in batches, to avoid constantly re-rendering the UI. This is likely to be an issue no matter what you're doing.
That being said - I'd question your overall visual design here - if you're trying to display over 1200 questions to the user, some form of paging is probably a much nicer approach than a huge scrollable container. If you page these, you could load and process the first few (which is probably near instantaneous, since you mentioned you can process about 50 questions/second), and then continue loading the others after the first few questions have been displayed.

How to clear keyboard buffer from stale messages

My WinForms application has a button. This button has accelerator key (e.g. Alt+L). When button is pressed I handle the Click event and disable UI to prevent further button clicks until processing is finished. However, when accelerator key is pressed using keyboard those keystrokes are queued and get processed as soon as UI is enabled again. I don't want this. My question is how to clear/flush keyboard buffer?
If I use KeyPress or KeyDown to eat those characters I don't know when they have been received. I only want to suppress old/stale messages that arrived when I was still processing first Click event.
Yes, indeed your theory of the problem is consistent with that proposed by both myself and madmik3 in the comment exchange above. The amount of work your application is doing on the UI thread is effectively blocking it from processing other events, including keystrokes by the user. Those are getting queued for later execution whenever your application finishes its time-consuming foreground task. Those are the perils of a modern-day, pre-emptive multitasking OS. Of course, without posting your actual code, the best I or anyone else can do is speculate about what the problem is, given our experience.
The quick check to confirm that this is actually the case is to toss Application.DoEvents into your processing loop. That will allow the OS to handle the keystrokes immediately, which will all fail because the button has been disabled. (Click events, whether initiated by the mouse or keyboard shortcuts, are not raised for a Button control that has its Enabled property set to "False".) This is the closest you'll get to anything like "flushing the buffers". I doubt you're receiving KeyDown or KeyPress events anyway until after whatever long-running task has completed.
If that fixes the problem, the long-term solution is to spawn a new thread and perform whatever processing you need to do there, instead of on your UI thread. This will prevent you from blocking your UI thread, and, assuming the Button control is correctly disabled, cause the keystrokes to get thrown away because the button they "click" is in a non-clickable state. The simplest way to create a new thread is using the BackgroundWorker component. The documentation contains a pretty good example.

Progress bar not showing until after task is completed

I have been trying to get a progressbar set to marquee to keep moving while another function is running. After this function runs, I message would display (for this example)
The only way I was able to get this working was with a background worker and then have a
Do
Loop until condition that runs in the main form until the operation is complete followed by my message box.
This seems like a kludge way to accomplish this and a thread.start followed by a thread.join seems like a much nicer way to fix this. However, I was not able to get that working either.
I have included a small demo program if anyone is interested.
http://www.filedropper.com/progressbar
Thanks
Thread.Start and Thread.Join is not the way to do it - that basically blocks your UI thread again. Application.DoEvents isn't the way to go either - you really do want a separate thread.
You could then use Control.Invoke/Control.BeginInvoke to marshal back to the UI thread, but BackgroundWorker makes all this a lot easier. A search for "BackgroundWorker tutorial" yields lots of hits.
EDIT: To show the message when the worker has finished, use the RunWorkerCompleted event. The ReportProgress method and ProgressChanged event are used to handle updating the progress bar. (The UI subscribes to ProgressChanged, and the task calls ReportProgress periodically.)
That is not a kludge. That is the correct way of doing it; what happens with the BackgroundWorker approach? The trick is to use the ReportProgress method to push the change back to the UI (don't update the ProgressBar from the worker).
Use Application.DoEvents() in your function from time to time so that your process has some time to process his events, including redrawing the form.
Alternatively, you can use a worker thread (like a BackgroundWorker) to process your treatement, while the UI thread is displaying your progress bar.
Complementing the answer given by Marc Gravell, the BackbroundWorker has a boolean property WorkerReportsProgress, if it is set to false, when you call ReportProgress, the program will raise an InvalidOperationException

Resources