Code Execution Sequence - vb.net

I am a PLC programmer who is currently using a variant of VB to control a motor.
I want to call a function that will execute moves and not return to the main code until the move has been completed. Currently here is what I have:
Program 'Main Program
While 1
If move_req = 1
Function MoveMotor
End If
Wend
End Program
Function MoveMotor
MoveABS 10 ' Move to encoder position 10mm
move_complete = 1
While move_req = 1
'Do Nothing
Wend
End Function
For some reason this code isn't working and the move command is being sent over and over again. Could this be because the main program continues to run when the function is running? Is that how VB works? I am used to thinking of code sequence in terms of PLC's where they scan through everything repeatedly at a certain frequency.

Whenever the move is complete, there must be a way for it to be detected by the program. It looks like you want move_req to be set to zero when this happens, but I cannot see what would cause that. How does the machine signal the program that it's finished moving?
A second point is that when you have a loop that waits while it checks for variable change, it can cause a CPU spike. You can put a pause in the loop with some thing like System.Threading.Thread.Sleep(100) where 100 is milliseconds to pause.

Related

How to limit the number of processes being spawned at a time?

I am working on a VB.NET Windows Forms application where the user is supposed to be able to determine how many processes the application is allowed to launch at a time.
My current method mostly works but I've noticed that occasionally the application goes over the set amount. I use two global variables for this, _ConcurrentRuns which is 0 at the start of the application, and _MaxConcurrentRuns which is set by the user.
Private _sync As new Object()
' This is called Synchronously
Private Function RunModel() As Boolean
If CancelExectuion Then Return CancelCleanup()
Do While True
SyncLock _sync
If _ConcurrentRuns < _MaxConcurrentRuns Then
Interlocked.Increment(_ConcurrentRuns)
Exit Do
End If
End SyncLock
Threading.Thread.Sleep(50)
Loop
'This is what will launch an individual process and close it when finished
ret = RunApplication(arg)
' The process has been closed so we decrement the concurrent runs
Interlocked.Decrement(_ConcurrentRuns)
Return ret
End Function
The goal is to let only one thread exit the while loop at a time, I'm not able to catch it in the debug mode however in the task manager it will occasionally go 1-3 processes over what it's supposed to use. This makes me assume that somehow multiple threads are getting inside the synclock somehow, but I have no clue how that could be happening.
I will be very grateful for any and all help that can be provided, thanks for taking the time to read my question.
So it appears that my solution works for this, I don't want to delete this question because it might be helpful to somebody else in the future.
Answer: Use better process monitoring software / set priority to high in task manager.

.NET Equivalent for VB6 DoEvents + Sleep

I have a program that I'm updating from VB6 to VB.NET that is used for making optical measurements. The hardware runs Win XP or Win 2000 Embedded. In the original code, there is a section that is triggered after a measurement is started that uses DoEvents and Sleep:
While instDefItf.InstrumentState = Busy
Sleep 500
DoEvents
Wend
I've tried replacing the middle two lines in my code with a simple Threading.Thread.Sleep(500) (I realize that this is probably poor practice, but not having a ton of experience with VB, I was trying to preserve the VB6 program as closely as possible). This makes the code work correctly - on the second try. On the first try, the measurements that are supposed to be taken simply aren't, but no errors are thrown and the subsequent code executes correctly.
Based on this, I have two primary questions. First, is there something I could simply replace the VB6 code with to get the desired functionality? Second, is there a better way to periodically query the instrument state that doesn't make use of the Sleep function?
EDIT:
The function I referred to above is a helper function (I think that's the right term) that checks to see if the instrument has completed its measurement. The measurement routine is contained within a DLL, and the code that executes it is given below.
If cbMeasLength.Value = vbUnchecked Then
Call I12001Ref.StartMtj1IlAcquisition2(CLng(lChannel), ConnectorA, m_moduleCollection.ReflectanceModule(lRm).SerialNumber)
End If
' Wait the measurement completion
If cbMeasLength.Value = vbUnchecked Then
If WaitForOperationCompleted = False Then
Exit Sub
End If
End If

VBA: Jump to the beginning of a for loop

I have a little problem with jumping back to the start of a for loop.
Part of the code:
For M = 1 To System
Openhours = Numberofhours(M, 1)
If Openhours = 0 Then
M = M + 1
Exit For
End If
I can have 1-6 "Systems", more could be added. "Openhours" says how many hours is dedicated to a particular system, but the problem is that if I happen to have a system (say system number 3) where there are no hours dedicated to at the moment, then the system crashes as, for example "Openhours" is zero with quite a few other arrays.
So I'd need to tell the code that immediately if it notices that Openhours is zero that it goes back to the beginning of the loop and tests the next system.
"Exit For" did of course not work as it skipped all the other systems after it found the first system with zero hours.
You could either check for Openhours being NOT equal to 0 and only execute your code in those cases, thus eliminating the need to jump to the next iteration or you could use the NEXT-keyword to jump to the next iteration of your loop.

Constantly updating "Status Form" locks over time

This is my first time using VBA in Outlook so please bear with me
I've created a basic Macro that does various things to folders. Since this takes a while I decided to make a status window that says what its currently doing. I simply keep setting one of the label's values with this
Function UpdateStatus(Message As String)
StatusForm.StatusUpdate.Caption = Message
StatusForm.Repaint
End Function
The issue is that after it runs for a bit (5-15 seconds) the window and the rest of outlook locks; the form no longer updates and has a "(Not Responding)" in its window title.
I feel like I'm somehow dead locking the UI thread but I'm at a loss on how to work around it. Commenting out Repaint not surprisingly doesn't let it update at all, but outside of that I don't know where to look
Any suggestions?
Try adding DoEvents in your computationally intensive loop. This yields the executing code to the UI thread so that other things can get done when you have computationally intensive stuff going on in the background. Office is single-threaded, so you can block the UI when you are running macros.
Sample:
Sub LockUI()
Dim x
x = Timer
Do While Timer - x < 5
'Blocks the UI for 5 seconds
Loop
End Sub
Sub LockUI2()
Dim x
x = Timer
Do While Timer - x < 5
'Doesn't block the UI
DoEvents
Loop
End Sub

VB.NET - Interrupt form loop and end form

I have a form that goes through an endless loop and processes data. When I click a button that "closes" the form, the form keeps processing even though it is closed. I want the form to completely end and exit out of its loop statement, and then open a new form.
Here is the code I am using to close the form
frmMain.Close()
frmMain.Dispose()
Note: I am not using threads it's just a simple VB.NET application. I am not closing the main startup form.
The "correct" way of doing this is with background worker threads really. But this will also work without the need of background worker threads.
Declare a variable in the form class.
Private keepLoopAlive As Boolean
Then write your processing loop to be something like:
keepLoopAlive = True
Do While keepLoopAlive
(your code that loops here)
DoEvents
Loop
Then on your Close event do:
keepLoopAlive = False
Me.Close()
This will cause the loop to end first chance it gets, and your form should close.
Please note I've written this code from memory and not in an IDE so there may be typos.
I am not a .NET developer so this may not be valid, but if I were performing an infinite loop, I would be checking each time I started that the loop was still valid with some sort of boolean value, and if it failed, drop out of the loop.
When you close the form, set the boolean value false and it will drop out, and you can either have an outer loop that waits and restarts the loop, or you can restart the entire function some other time.