How can I force a progress bar to update during a long-running operation in VB.NET? - vb.net

I am running a test program for VB.NET, and it will simply crunch a million numbers in for loop. I've linked a variable implying the progress of the for loop with the progress bar, but it seems that when I run the program, the progress bar does not update itself. The bar itself has only value 0-100 as input (as stated in the document) and I've tested it without using the for loop, and it works.
I think this has to do with threads, but I am not sure how things work in VB.NET exactly yet. So I want to seek an advice from an expert first.
Any advice is appreciated.

Don't know if this still applies for .net (or if this is a VB6 question), but Application.DoEvents was generally the solution in VB6 days.
Try Application.DoEvents inside your loop that updates the progress bar.

long time ago but i think you need the
DoEvents
statement

Related

Update UI with progress during UI-intensive loop

I've got a long-running loop which involves a fair amount of UI functions. This loop therefore must be run on the main thread. However, I also want to display progress of this task, so this must also run on the main thread as displaying the current progress would involve updating the UI. I am really struggling to find a way of allowing the UI to update with current progress on the main thread when the main loop is also running on the main thread. What happens is that the UI is frozen during the loop and then updates to show that the process is finished when it's done.
This is not for a production app, it's for a personal project that will never be release. So it is of no concern that the UI is frozen from a UX perspective. If the solution involves putting the processing in the background then this refactoring is fine, but I'm not sure how to do it when a lot of the heavy lifting during this loop involves UI stuff too.
Isn't it funny how you sometimes come up with a solution just after posting the question?! The key seemed to be rather than using a for loop for the processing, instead putting the processing function inside a separate method and repeatedly calling it, passing the array of objects to process to it. Doing this, you can call the function using [self performSelector:withObject:afterDelay:]. Even if you provide a value of zero for the delay, it causes the method to be called on the next run loop. This means you can update the UI, process the next item, and repeat this process until the array of items is empty. Here's my completed solution. If anybody knows a better way I'd still love to hear it, but for now this is at least working!
Edit - I packaged this solution up into a class of its own to make it easier to manage, and put it on my Github. Maybe it will help somebody else out :)
Edit 2 - made the processing class more flexible by making it run loops instead of iterating through arrays. You can of course use it to iterate through an array yourself, as per the example in the readme. But if you're not working with an array, you can just run the loop runCount times and do whatever you need to do in the processingBlock.
https://github.com/mashers/BackgroundLoopProcessor

Thread queue with timeout in VB . NET

I have a function which does some tasks in database trough a function contained in a dll. That function need to be executed many times with different parameters, but sometimes it takes too much time and need to kill the process and continue with the queue. The function in de dll doesn't have any timeout option, so I tried to control this creating a thread. I'm not used to work with threads, but after some research I made something like this code:
Dim Thread As New Threading.Thread(AddressOf Function)
Thread.Start()
Thread.Join(maxTime)
If(Thread.IsAlive) Then
WriteLogFile("Error [....]")
Thread.Abort()
End If
Probabily it isn't the smartier or most elegant way to do it, but it seemed to work when I tested it, but now I see that the "timeout" doesn't work. Well, it seems to work well if I set the timeout with a few seconds. But if I set it to 10 minutes, which is what I need, takes much more time than 10 minutes. I can expect that maybe Thread.join() is not totally accurate, but the difference is not jsut few seconds.
I tried many similar ways, so i don't know if i have the right focus of the problem. Maybe the malfunction of the code comes from the way of work of the .dll function, but first I need to discard the posibility of a mistake from myself (which i think is more probabily).
¿Can anyone tell me where is the mistake, or another way of doing this safer?
Thanks in advance.
Answered from comment of Hans. In order to control the execution of unmanaged code, threads can't provide a proper handling to finalize the function, so to implement a true timeout limiter, is needed to launch that function inside other project called as a process, to be able to call Kill() function, which really stops the process.

VB .net Infinite Loop/Interrupt Driven

I'm pretty new to VB .net still and I'm attempting to write a program that constantly watches information pulled from a PLC and updates when it changes.
I've worked some with microcontrollers and I know making an infinite loop works well. What I'm running into with my VB .net code is when it loops, the form basically freezes up and the label never updates. I attempted using the code below.
Do While True
*Code*
Loop
So, I guess my first question is, what is the best way to go about having a continuous program to update data. It seems an infinite loop is not the answer.
My second question is, like microcontrollers, is it possible to have VB .net be an interrupt driven program instead of an event driven. My program is always running, updating the data as it comes in, but if a button is pressed it can essentialy break out of the loop. Or what I have in mind, temporarly leave the loop to perform another function then continue back into the loop.
I've looked at the System.Timers namespace, and am not 100% clear on how they work. It seems like it is potential answer to my problem. If I have a timer that does the code every one second, this one second occures as long as the form is running correct? Assuming the previous statement is correct, if the code is running from the 1 second tick, and a button is pushed while that code is running, will the button be ignored, or will the event happen after the code has finished.
Anything to help me learn will be greatly appeciated!
You can use the
Application.DoEvents()
-method provided by the .NET framework, it essentially updates your form to apply all the changes that happened in the meantime.

Excel freezes during execution

When I execute my code (which takes 3-4min. to execute) in Excel, and I click on something in excel or in my userform, it freezes, gets white, almost crashes... When the execution is ready everything is fine again.
Of course it is normal that I can't work in excel during execution, but how can I avoid the "crashing" of excel?
Do you have a Loop in the code?
If so, add the following line just after you initialize the loop and it should help with your problem!
DoEvents
The best way to prevent these kinds of issues is to benchmark your code to determine what is taking so long. If your code is taking over 3 minutes to run, you almost certainly have room for optimization.
Here are the steps you need to take:
Set multiple breakpoints within the code that is executing.
Time how long it takes to get from one breakpoint to the next.
Once you've identified the culprit(s), refactor.
If you aren't able to improve performance, post the inefficient code and ask for help.
A notorious slow-performing anti-pattern to look out for is selecting things during a loop.
What you need to do is create a custom UserForm that will overlay the Excel UI, like a Progress Bar. You'll also want to look into ways to force your form to stay ontop, much like a modal form. You can't use modal form's because they cease execution.
After you make sure there are no infinite loops making excel unresponsive try optimizing your code.
I found this a very interesting read on vba-excel code optimization and some of the practices actually had an impact on a big and time consuming module I wrote. Hope it helps.

Why does this program need MsgBox?

Long story short: I'm trying to write an app that'll dump IE's history to a text file. Because I am lazy, I went searching for a preexisting library and found this beautiful project to build from: http://www.freevbcode.com/ShowCode.asp?ID=6702. Only, I'm stuck...
I finally got the program to dump the history, but it only works if I put a MsgBox() on line 169 of Module1.vb. I've tried putting a Thread.Sleep() there, but that doesn't work. There has to be a message box there, or only today's history gets listed.
My guess, since this is talking to wininet.dll, is this is a concurrency thing. Thread.Sleep() (for a For...Next loop) stops the program from listening; nothing there makes it exit the loop before values are assigned, but a MsgBox() is just right. Is there something besides MsgBox() that will have the same effect? I'd like to not have to hit OK thirty times to make the program work.
Here's my branch/version/derived work: http://profnano.org/andy/misc/img/HistList.zip; it's a VS.NET2003 project.
MsgBox() pumps a message loop. That can get all kind of code unstuck. Windows get a chance to paint themselves. COM deadlocks due the main thread getting stuck in a loop are solved, always an issue when IE is involved. Calling DoEvents() is the very imperfect alternative to MsgBox().