I am writing a program (in Microsoft Visual Basic) to control a remote instrument (an XY axis microscope stage). As an example, the user must initially calibrate the stage by clicking a GUI button. It takes some time to accomplish the calibration process and I do not want to freeze the main GUI, so I execute the call on a background thread, as follows:
Call New Thread(AddressOf CALIBRATE_STAGE) With {.IsBackground = True}.Start()
So that works well, but we can imagine that for some reason, the user might need to halt the calibration before it is completed. The halt command must originate from a button on the GUI but it cannot be run from the main thread, or a HUGE instability results. (Basically, a program crash, probably because the sub thread was incorrectly managed. The only fix is to completely reboot the computer.)
I think what I need to do is something like this pseudo-code:
Press HALT button on GUI
Execute the STAGE HALT command on the same sub-thread where the CALIBRATE_STAGE command was launched
Once the stage is halted, properly abort the sub thread
Trouble is, I do not know how to do acquire the specific sub-thread on which CALIBRATE_STAGE is running. I do know its ThreadID, but given that integer, how do I launch a new process on that thread? Does anyone have some ideas?
Or maybe someone knows this idea of mine will not work and has a better solution?
Related
Scenario
Using Delphi 2009 on Windows 10 I have an app that performs shut down operations such as logging and database manipulation.
Anywhere the user is able to exit the app I call Form.Close on the main form which calls a procedure to do the required operations. This works ok regardless of whether the user exits via the menu or by using the Windows task bar icon to close the window (as some of my users do).
Problem
When debugging the app in the IDE however, clicking the red square in the Delphi menu bar to stop the app running does not call Form.Close and hence doesn't call my shut down procedure.
Question
Is there a way to make the app correctly call form.close when shut down via the IDE so that I can ensure all parts get debugged?
Other info
I've looked here which describes a method using WMQueryEndSession to catch windows shut down messages but when I use that code in my app it is not called when the IDE shuts down the application, so maybe the IDE is using a different method.
Code used in my WMQueryEndSession procedure
procedure TFrmMain.WMQueryEndSession(var Msg: TWMQueryEndSession);
{intercept the shut down message and call our proc first
SafeFormClose is very simple and quick so no issues.
Also called first in case the inherited procedure shuts us down
before SafeFormClose has a chance to run}
begin
SafeFormClose; //Do our shut down and logging stuff
Msg.Result := 1; //Signal that it is OK for Windows to shut us down
inherited; //Do whatever the original handler would have done.
end;
If you are running the program in debugger, clicking the red square (reset button) terminates the program immediately. The debugger has full control of the program, and no more code is run after you click the reset button.
This is different than for example terminating the program in the task manager (in which case Windows would send a close signal to the program, which could reject it if it doesn't want to close yet).
You should design the program so that if it stops at any point, the next time it is started it fixes any problems caused by the reset (for example fixes corrupted database files). This is a real situation that can occur when power is lost or the operating system crashes. You cannot trust that your shutdown routine can be run every time.
Title quite much says it all.
In VB6, and in VBA/Access it was possible to hit break key, and jump into debug mode when using the msgbox() command.
Is there a way to do this in vb.net (desktop/winforms) applications?
Often, some code will toss up a dialog box, and it is rather nice then to jump into debug mode as a result of that message box having been displayed.
Edit
Ok, hitting pause button in most applications work, but in this application, when I hit pause, then I get this:
Edit two:
Ok, I have discovered the reason for this behavior. I have the application Frame work box un-checked. The reason for this is I did't want to specify the main application form as startup form, and I desired additional control over what occurs if the main startup form (that I don't specify) is closed. Thus, my main application form is launched via application.Run(my form)
It thus seems that due to starting the main form as a new separate application thread (which is the result of using application.Run(), then you can't use ctrl-break, or more common use/hit the pause button in the IDE to halt the code. Hitting pause will thus display that the application is running a main app thread, which indeed is the case since I use applicaiton.Run() to launch the main form from the classic and traditional Sub Main().
Edit 3
A way to fix this, and enable the pause key to work is to un-check in tools->debugging the [ ] Enable Just My Code. This will thus allow debug mode of the other "main" application thread.
Hmm. [CTRL][BREAK] clears the dialog box. However, clicking the pause button in the IDE will do what you want.
Alternatively, select Debug > Break All from the menu.
I'm look for code which can help me accomplish what the title suggests.
I want this because I have an issue with a program which is quite buggy (it's a game), and if It freezes, and results in a black screen. Even after using Shift+Ctrl+Esc, Ctrl+Alt+Del, Alt+F4 and the rest of them, I acn't seem to end the program. So I thought that a KeyPress event would work, as it doesn't require me to use the UI in any way.
However, I've never used VB for anything other than Form's, so I have no idea how to start on something which runs in the background.
Thanks :)
A background app won't help in this case.
Ctrl+Alt+Del is specail key combo that is handled directly by Windows and can't be intercepted by a running program.
What this means is that if your game locks up and Ctrl+Alt+Del doesn't bring up the Windows menu, then the game has corrupted the system. The only fix at that point would be a restart.
That being said, you can kill a running process using VB.NET like this:
For Each program As Process In System.Diagnostics.Process.GetProcesses
If program.ProcessName = "ProcessName" Then
program.Kill()
End If
Next
Read more about it on the MSDN.
Okay, so Windows isn't actually locking up, but you just need some way to kill the process. Use the above code, replacing "ProcessName" with the name of your game process, and then either:
(basic) Turn the VB.NET code into an .exe file. Then set up a keyboard macro (using your keyboard software or some freeware) to launch the .exe you made which will kill all running instances of the given process. or...
(advanced) Import "user32.dll" into the VB.NET code, call SetWindowsHookEx with a hook id of 13, a pointer to a LowLevelKeyboardProc function, the handle to your running program, and a thread id of 0. Then, whenever a key is pressed in any program, your KeyboardProc function will be invoked. If the key(s) pressed match your desired kill-key combo, then run the above process killing code. This looks like it may give you more step-by-step instructions.
I have a program that has the option to create a restore point...
My problem is that when you click on it to do so, the program just locks up until it's finished creating the restore point.
I have put a seperate form on the program and it has a Marquee Progress Bar Control which I downloaded, so the idea is...
User clicks "Create Restore Point"
frmRestore.show
Marquee Progress Bar goes on and on while the restore point is created
Restore point is done
frmRestore.hide
The thing is, when you click create restore point, the form shows and the program just locks up, onces the restore point is created the form hides again.
Could this problem be solved with a Background worker? To be honest I'm not completely sure what it does, I mucked around with the controls but can't seem to find anything useful.
Thanks
You need to put the restore procedure in separate thread. If your program is not multi-threaded then it will work linear and lock until it will finish the task it is doing.
The program is locked up because you are doing something intensive on the main thread.
It goes like this in a GUI application:
// do some stuff
// respond to system and redraw gui
// do some stuff
// respond to system and redraw gui
And when you block "// do some stuff" the program won't be able to respond and redraw the gui untill do some stuff is done.
What you need to do is either use a secondary thread or using a background worker like you said. A thread is like, you can do stuff in it without blocking the system or the GUI
hope this helps
I've never seriously used VB, but I think the same concepts apply to Qt (begin rant about Qt being better here).
I'm not sure if VB uses a GUI thread or just one unified one, but I think your problem is that the GUI thread is performing long non-gui operations which cause it to "lock". When it "locks", the program is waiting for the tasks to finish, and hence not letting you interact with it.
Use a separate thread...
I have a python script that is running in the background with pythonw. If I close my laptop, it goes into sleep mode. and when I open my laptop, my program has little functionality and freezes after a couple of seconds. Is there any way that my script can tell if my computer is going into sleep mode, so that it can lie dormant and restart when I re-open my laptop?
You can catch WM_POWERBROADCAST window message with PBT_APMQUERYSUSPEND event inside it. To catch this message inside Python program, you can create new invisible window and make separate thread repeatedly calling GetMessage().
In the worst case you can archieve all these by using ctypes only, but you can also use pywin32, sometimes referred to as win32py.