I need read in an infinite loop some variables and in the case it changes the boolean status it must do something.
I tried to use a Do...Loop but the application crashes.
Is there a way in visual basic 6 to use an infinite loop without stunk?
My code:
Do
asd1 = readValue1
asd2 = readValue2
If asd1 <> asd1ex Then
Text1.Text = "yes"
End If
If asd2 <> asd2ex Then
Text1.Text = "no"
End If
Loop While True
Make a timer and on that timer check the status, instead of the loop.
Solved after comment that explained where the data was coming from (async COM component's property):
working with vb6 IDE on a realtime client-server project. I have to read some variables
and when one of these changes status it sends a socket message to
server. With the sleep it stuck equally
What did not help:
DoEvents and sleep
DoEvents
Sleep 100
might help, will need to refer to the windows function sleep. But VB6 is single thread (well one for UI and one for logic) so you should have a way to get out of the loop. What are you really trying to do? Can you describe at a top level?
Are you working on the VB6 IDE or in VBA code in Office?
For sleep to work declare:-
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
See this too https://stackoverflow.com/a/4540553/1643558
If your showing a form to the user to read value 1 and 2 then you can use a modal form and have a button to click when they are done, and hide the form only when you like the values. No need to have a loop then. Can show an error MsgBox on a modal form too.
See http://www.tek-tips.com/viewthread.cfm?qid=1117372
Maybe remove the sleep and only keep the DoEvents.
You could also make a timer and on that timer check the status, instead of the loop
It looks like you're trying to set up a sort of event handler. In effect, your loop is "listening" for a change to the variable. You don't explain how the variables get changed, and this is important . If whatever is changing the variables can also raise an event, then you're home free--you can get rid of your loop and use the event handler to send the socket message. (This is probably why Deanna asked how the variables change.) This is the preferred way to do what you want, so you should find ways to raise an event if the variables change.
Related
I am using this script to close all "Alerts" in my notification bar:
tell application "System Events"
tell process "NotificationCenter"
set numwins to (count windows)
repeat with i from numwins to 1 by -1
click button "Close" of window i
end repeat
end tell
end tell
However this doesn't close them all, even when there are no "Alert without Close button".
try catch didn't help. What's wrong?
I tested your script and it seemed to run correctly on my machine, but there is always a potential for problems when you use a repeat loop on a mutating list: in other words, a list that changes as the repeat loop progresses. Each time you close a window Notification Center changes its window list and updates the properties of the remaining windows; the script can simply lose track. I'm a little surprised it doesn't throw errors when this happens, but...
You can try this code and see if it works. rather than referring to windows by index it repeatedly tries to close the last window, ignoring any errors, and keeps on until the window count is zero or it loops 100 times (that last is to prevent an endless loop in case something goes wrong).
tell application "System Events"
tell process "NotificationCenter"
repeat 100 times
try
tell last window
click button "Close"
end tell
end try
if (count of its windows) = 0 then
exit repeat
end if
end repeat
end tell
end tell
EDIT
Per comments, the above doesn't work quite as advertised, so let's switch it over to AppleScriptObjC:
use framework "Foundation"
property NSUserNotificationCenter : class "NSUserNotificationCenter"
NSUserNotificationCenter's defaultUserNotificationCenter's removeAllDeliveredNotifications()
This seems to do the trick on my machine. Of course, NSUserNotificationCenter is deprecated as of 10.14, so this won't work forever — eventually you'll have to shift over to the notification's framework — but it should work for a few more OS versions.
EDIT 2
Per another comment, anyone working on os 10.14 or later (Mojave and Catalina, to date) can do an equivalent AppleScriptObjC routine using the UserNotifications framework, like so:
use framework "UserNotifications"
set notificationCenter to class "UNUserNotificationCenter"'s currentNotificationCenter
notificationCenter's removeAllDeliveredNotifications()
Note that I've used a slightly different syntax (merely calling class "UNUserNotificationCenter" rather than setting up a property). Both work; the property syntax is only preferable when you need to pass the class to handlers.
Ok, here's my use case. I have a form that pulls different parts of the form from a number of tables in a database. Each time I pull the info, I test to make sure there were no errors. Currently I'm using msgbox to show if there are errors, but I'm rewriting the app to instead display these messages in a "status" line area. It's just a label that I write the strings into on the form that flashes the error. This is working great in my single "You did this, and you got an error" forms. But in one of my forms it's about 6 things that could give errors, and it's on load. So it's not a single action, single error type deal.
My idea is to load any errors into an array, then display them one at a time for like 5 seconds each, then loop back and do it again, for at least 5 times. So in effect I want it to show each error, for 5 seconds, then show the next one for 5 seconds, then start over again, for 5 times, then stop.
Problem is, while I've got about 10 ideas on ways to maybe do this, they all seem really complicated and complex (and I don't want to spend 10 hours writing it only to figure out it's not going to work). I'm looking for the "best" way.
So.... Is an array even the best way? Or would a list or some other way be better? I'm looking for ideas here. How would YOU do it?
Eventually, you can use arrays for what you are trying to achieve. This could be done by following the steps :
When you are pulling the information from the tables, check for errors and if there is any, put it into an array.
Define a for loop which is going to loop 5 times
Define another nested loop to loop through the array to display the messages one by one
After each message display, put a sleep or delay of 5 seconds
If you follow these instructions, it just a matter of minutes into writing the codes
I ended up solving this by using a combobox and a list, then just having my combobox blink. On forms that can only throw one error, I use a label instead. Here is the lion's share of my code to do this:
Private Sub ErrorCheck()
If errorList.Count = 1 Then
ErrorComboBox.Visible = True
DismissErrorButton.Visible = True
For Each errors As String In errorList
ErrorComboBox.Text = (errors)
Next
ErrorBlinkTimer.Enabled = True
ElseIf errorList.Count > 1 Then
ErrorComboBox.Visible = True
DismissErrorButton.Visible = True
ErrorComboBox.Text = "There were errors, click drop down to view!"
For Each errors As String In errorList
ErrorComboBox.Items.Add(errors)
Next
Else
End If
End Sub
What I do is after each thing in a SUB that can throw errors, I have it collect the error and write it to errorList with errorList.add like so:
Catch ex As Exception
Dim errorStr = "An Error Occurred in " & Me.Name & " writing into the OpenEvents table " _
& "for setting the Alert radio button."
log(errorStr & " - " & ex.Message)
errorList.Add(errorStr)
the log function is a custom function for writing off to the log, but the rest is standard VB.net stuff. As you can see, if I get any exception (I do the same thing with each query too) it writes the error off to the errorList, then flashes the combobox with the error(s). I have some more logic to make it all nice and pretty, but you get the idea.
at the end of each sub that CAN throw errors, I just have it call:
ErrorCheck()
and like magic, if there were any errors a combobox list appears with bright red flashing text to let them know. If they click it, and there is more than one error, they can see them all in a nice list. Clicking it also makes it stop flashing, cause that would be annoying... LOL
This ended up working much better overall really, but it's not quite as pretty as my first way of doing it... but, no matter what I did, it caused issues on the form(s) to have it running through the flashing loop 5x's to display each error one after the other. I had found work arounds for most of it, but there was still a performance impact, so I dumped it for this. And it does the job well enough.
How do you make a breakable loop in Scratch? I'm using Scratch 2.0 and can't find any good way to make a loop breakable, from inside of the loop itself.
Disclaimer:
There is no perfect way to do it. If you can possibly stand this true fact then feel free to continue.
There are a few different ways you could do it.
With repeat until
The first and most simple one follows this:
But this isn't technically part of the script - it's just repeating until some value returns true.
With a custom block (stop this script)
In order to do it inside of the script, you'll need to use a sneaky little trick with custom blocks.
Create a custom block called whatever you want - but probably along the lines of "breakable loop". Inside of it, create this script:
By using stop script we are breaking out of the script that is currently running - which, according to Scratch, is the custom block.
See the result! (as scratchblocks)
With broadcast and wait
You could also use a broadcast-and-wait method, very similar to above:
Though I highly suggest you don't use this method, as if any other sprites have breakable loops you'll need to rename each one, which can be tedious after using a lot of loops in a lot of sprites!
(Note this bug has been fixed in version 442 of the editor and such the following no longer applies.)
Help! My project is lagging a bunch now!
As #foi has noticed, if your code must be run inside of a frame you probably checked run without screen refresh. Unfortunately, due to a bug in the Scratch player, this causes the program to essentially break after the stop this script block has been activated. How can you handle this?
It follows the same principle you use when you use a run without screen refresh custom block inside of a forever loop - the loop doesn't use screen refresh while the inside does, allowing for instant animations whether or not one is using turbo mode.
Here's an example - the image is really too long to be embedded, so see it here instead.
You can make a variable inside or outside of the repeat and make your script like this:
repeat until [[my variable] = [e.g: 1]]
your code
your code
your code
your code
end of repeat until
For a "repeat until" block the simplest way would be to "or" your normal until condition with the break condition in the until.
By adding an incremeting loop counter variable in the loop you can use a "repeat until" to replicate the function of a "repeat n times" block
By using a "repeat until" block with only your break condition you get the equivalent of a "forever" block
If you need another script/ sprite to trigger the break then a public variable will let you break the loop from anywhere and let a single condition break loops for different sprites.
I'd post an image of the blocks but this is my first reply and the site won't let me!
good luck
You can use these few ways to do it...
conditional loop
stop this script
if then else, in the else section, put nothing
I would prefer to use the first method, as it requires less blocks and for the first method, you can still add in code that will be executed after the loop has stopped executing.
You can make it repeat x times or make it have a certain point where it stops, such as another variable changing.
Otherwise, I don't think there is a wat to do that.
Use the repeat until block. Then put in an equals block or whatever into the boolean part. Then inside that repeat until block, put a stop this script block.
Hope this helps :D
I am no longer "new" to Python, but am now moving into unchartered territory.
Recently I was dissecting some logic circuit code found here. I learned a lot about the practical use of inheritance from this code. Good stuff.
Not much happens in this code until one changes the inputs on a gate, so the interpreter must be used to manipulate the inputs. I got tired of using the interpreter, and so I investigated ways to create a continuous loop that would not rerun the initial code.
I found that Tkinter uses a continuous loop that I could then interrupt with the "after" method to update some of the parameters of the code currently running.
That works well, however I am curious as to whether there is another and/or better way. Anyone know of one or the other?
Some of the code:
tk_TkGUI = Tk()
f_AndTest() ## Initialize the 'And' gate
tk_TkGUI.after(1000, f_ChangeAnInput) ## Invokes Tk 'after' method to update an input
tk_TkGUI.mainloop() ## Must be used in Windows with Tkinter
def f_ChangeAnInput():
A1.B.set(0) ## Change A1.B from 1 to 0
If you want a window, using Tkinter in this way is perfectly fine.
By the way, after doesn't interrupt the loop as you described it. The main loop simply loops over a queue of events and processes them in order. When it reaches the end it waits for more events. Much like when you press a key or move the mouse, after merely puts something in the queue to be processed later. It really is as simple as that.
you could use threading.
import thread
def blaH:
#All your code that isn't related to your tkinter stuffs in here
thread.start_new_thread(blaH,())
the only thing is that you need new ways of both threads to talk to each other, such as global variables.
I'm extending a GTK-application that does a group of operations that takes high CPU loads. I want to include the possibility to stop this operation by clicking on a button in the GUI.
The problem is that, as expected, the signal coming from the button is actually fired just after the operation is completed.
For now, the code kinda looks like this:
[...]
// code snippet to show the dialog and to enable user interactions with the buttons on the lower side of the window
while(TRUE) {
gint run = gtk_dialog_run (window_main);
if (run == GTK_RESPONSE_APPLY) {
gboolean success = start_long_operation();
}
else if (run == GTK_RESPONSE_HELP) {
open_about();
}
else if (run == GTK_RESPONSE_CANCEL) {
stop_long_operation();
}
else {
gtk_widget_destroy (window_main);
return;
}
}
I've declared a global variable busy_state that is checked by the long operation's function: if it is TRUE, simply the inner loop continues to cycle. Else, the loop exits and the function returns a result.
stop_long_operation() simply sets this global var to FALSE.
As written before, I can't press the "stop" button and "send" GTK_RESPONSE_CANCEL until the operation finishes, because it blocks the entire window.
I've tried the use of while (g_main_context_iteration(NULL, FALSE)) trick inside the stop_long_operation() function, as explained in the gtk's docs, but without results.
Do I really need to set up a multithread functionality? Can I avoid this?
Thanks for the help.
If you can break up your long operation into multiple smaller tasks you may be able to avoid using threads. The easiest way would be to just create a callback that you would pass to g_idle_add (or g_idle_add_full). Each time the callback runs it does a small amount of work, then returns TRUE. When the the task is completed, return FALSE and the callback not be run again. When you would like to interrupt the task, simply remove the callback by passing the value returned by g_idle_add to g_source_remove.
If you can't break up the operation then threads are pretty much your only choice. g_thread_new is the low-level way to do that, but it's generally easier to use a GThreadPool. A more advanced option would be to use g_simple_async_result_run_in_thread.
Here's another option if you don't want to use threads (although you should use threads and this is very insecure):
Use processes. Processes are much simpler, and can allow you some greater flexibility. Here's what you need to do:
Create another C/C++/Any language you want program that does the task
Spawn it using spawn() or popen()
(Optional) Pass arguments using the command line, or IPC
When the button is pressed, use either the kill() call on UNIX, or the Win32 kill function to kill the process. You can use SIGTERM on UNIX and register a handler so that you can have a controlled shutdown.