How to implement multi-threading in visual basic 6.0. It would be great if someone can give an example.
VB6 is not a really good environment for multi-threaded applications. There is no out-of-the-box support, you need to delve into standard WinAPI functions. Take a look at this article, which provides quite a comprehensive sample:
http://www.freevbcode.com/ShowCode.Asp?ID=1287
On several projects I have implemented asynchronous processing in VB6 using multiple processes. Basically having a worker thread within an active exe project that is separate from the main process. The worker exe can then be passed whatever data it needs and started, raising back an event to say it's finished or there is data for the main process.
It's a more resource hungry (an extra process rather than a thread) but VB6 is running in a single threaded apartment and doesn't have any built in support for starting new threads.
If you really need to have multiple threads within one process I'd suggest looking at using .net or VC6 rather than VB6.
If the problem that you are trying to solve is a long calculation and you want to keep the UI responsive, then one possibility is to frequently call the DoEvents function within your long calculation. This way, your program can process any Windows messages, and thus the UI will respond to user commands. You can also set up a Cancel button to signal your process that it needs to end.
If you do this, then you will need to be careful to disable any controls that could cause a problem, such as running the long process a second time after it has started.
Create "Active X" controls to manage your code. Each control has its own thread. You can stack multiple controls doing the same thing, or have individual controls doing unique things.
EG, You make one to download a file from the net. Add ten controls and you have ten individual threaded downloads running, independent of the thread which the actual program is running. Essentially, they are all just interactive, windows, controlled by an instanced mini-dll program.
Can't get any easier than that. You can throttle them, turn them on and off, as well as create more, or remove them, as needed. (Indexing just like any other of the "Objects", on a form. Which are all just active-x controls, which are simply managed by the vb-runtime dlls.)
You can use the Interop Forms Toolkit 2.0 for multithreading in VB6. The Toolkit
allows you to take advantage of .NET features without being forced onto an upgrade pat. Thus you can also use .NET User Controls as ActiveX controls in VB6.
Related
Are there any libraries that I can import into a VB6 project to enable multi threaded support? I know that there are examples using the Windows API but I was wondering if there are any libraries that already exist that I can just import into my project to allow this functionality in VB6. I have inherited a very complex application in VB6 that one of its tasks is to control a multi-million dollar robotic arm. I need to take this application and make some changes that would benefit greatly if I can add multithreaded support. Converting this application to .NET would be an enormous undertaking (to us a good analogy would be the equivalent of a manned mission to Mars next year). The application includes several custom libraries that perform complex scientific calculations and data analysis. The code has been customized to deliver an impressive processing speed (this is VB6). It would take an enormous amount of resources to migrate to a .NET platform. Executive management indicates it could easily be 8 years before the system is upgraded. I would appreciate any responses.
Note: I did a search before submitting this question and I did see a similar question being asked but the answer to the question directs to the Windows API directly. My question is a bit different. I am asking about libraries that already include this functionality that I can use in this project. That is, libraries that have already done all this work of using the API.
There's no library for multithreading that I know of. But asynchronous processing does not necessarily require threads. Desaware have StateCoder, a library for state machines which helps with multi-tasking without multi-threading. A bit like the Aysnc CTP.
Alternatively here is a pretty standard scheme for asynchronous background processing in VB6. (For instance it's in Dan Appleman's book and Microsoft's VB6 samples.) You create a separate ActiveX EXE to do the work: that way the work is automatically on another thread, in a separate process (which means you don't have to worry about variables being trampled).
The VB6 ActiveX EXE object should expose an event CheckQuitDoStuff(). This takes a ByRef Boolean called Quit.
The client calls StartDoStuff in the ActiveX EXE object. This routine starts a Timer on a hidden form and immediately returns. This unblocks the calling thread. The Timer interval is very short so the Timer event fires quickly.
The Timer event handler disables the Timer, and then calls back into the ActiveX object DoStuff method. This begins the lengthy processing.
Periodically the DoStuff method raises the CheckQuitDoStuff event. The client's event handler checks the special flag and sets Quit True if it's necessary to abort. Then DoStuff aborts the calculation and returns early if Quit is True.
This scheme means that the client doesn't actually need to be multi-threaded, since the calling thread doesn't block while "DoStuff" is happening. The tricky part is making sure that DoStuff raises the events at appropriate intervals - too long, and you can't quit when you want to: too short, and you are slowing down DoStuff unecessarily. Also, when DoStuff exits, it must unload the hidden form.
If DoStuff does actually manage to get all the stuff done before being aborted, you can raise a different event to tell the client that the job is finished.
Disclaimer: direct copy of my answer on another question
You can certainly call the windows API to implement multi threading, and its not actually that complicated. However, the simplest solution would be to expose a .net Com object and implement multi threading through .net. For complicated already existing functionality you can break the vb6 app into com libraries that can be called by by the multi threaded .net controller.
[Gui] ┬> [ .net Com Mulit thread controller] -> [Com exposed VB 6 utility]
|
└> [Com exposed VB 6 utility]
See the article Using Background Threads with Visual Basic 6 for an elegant answer to the problem.
There was a threading library made by elitevb in 2002 which is unfortunately closed now.
But there is an archive of elitevb articles on xtremevbtalk.
In the section System and devices there is a post at the bottom with the threading.dll and sample source code attached, which makes it very easy to implement threading. As far as I remember, there was the problem, that testing it in the IDE crashed the program, but there were no problems running the compiled program.
With the library, you could create threads pretty straitforward:
Dim ReadValuesThread As Thread
Private Sub Form_Load()
Set ReadValuesThread = New Thread
ReadValuesThread.StartThread "ReadValues", "None", Me
' Public Function StartThread(FunctionName As String, _
' FunctionParameter As Variant, _
' ParentObject As Object) As Long
End Sub
Private Sub ReadValues()
' do things
End Sub
Private Sub Form_Unload(Cancel As Integer)
' kill thread
ReadValuesThread.EndThread
End Sub
We're starting a new custom project right now from a client and one of the requirements is the process cannot be terminated unless the system is shutting down, restarting, or logging-off.
This application monitors the USB interface. We will be using WMI to query the device periodically.
The client want's to run the application on Windows XP Operating System and doesn't like installing .NET. So we targeted Visual Basic 6 as our language.
My main concern is this application cannot be terminated. Our Project Adviser talks about Anti-virus and yes, some of the anti virus cannot be terminated. I was thinking how to do the same in Visual Basic 6. I know there will be API involved on the project but where should I go? so API is ok with me.
I saw some articles that converts the EXE to a SERVICE, create Windows Service in Visual Basic 6, etc.
So please .. share your thoughts.
If you want to be evil, you can call the (officially) undocumented RtlSetProcessIsCritical NTDLL function. This will immediately BSOD the machine if your process is terminated.
You cannot create a process that cannot be terminated without some sort of kernel-mode hooking, which involves writing a driver. You might want to look into Rootkits: subverting the Windows kernel if you're interested in that. However, even with kernel-mode hooking there are still numerous ways to terminate processes. The alternative is to use user-mode hooking, easily bypassed but enough for very simple projects.
The solution you want to use will depend on how far you want to go with the termination protection. And even if you do succeed in preventing process termination, there may be ways of preventing your application from working properly - e.g. killing the WMI service.
I think you want to look at writing an NT Service.
More info here: http://www.montgomerysoftware.com/CreatinganNTServiceinVisualBasic6/tabid/161/language/en-US/Default.aspxlink text
It's really frustrating coding in VB6 right now specially I dumped my head in C# for 2 years though I coded in VB6 for 5 years..
Moving back is a pain as if I am starting a new programming language.
To be honest, you are trying to do something in VB6 that it really isn't that great at.
When you say 'cannot be terminated' - what do you mean by that? There are several levels there:
a) App shows a window but the user cannot close it with the X button, or it does not show one
b) App shows no windows or maybe sits in task tray
c) App shows no windows and cannot be shut down from the Applications tab of task manager
d) App cannot be shut down from the process list of task manager
(a) and (b) are probably easiest to do in straight VB. (c) is still possible, but getting uglier. (d) gets you into hack territory and would almost certainly be frownd upon if you did manage it.
If you really need to stop users closing then you can probably hack it to a greater or lesser degree, but the real answer is as the others have said - a system service (this is exactly the srt of thing they were intended for). However that is one thing that VB6 isn't good at so the best solution to your problem is c#.
Using VB6
At the time of executing, it showing white blank screen while it was working with database,
How to avoid the white blank screen in VB6.
WHITE BLANK SCREEN MEANS HANGING (WHEN IT WAS WORKING WITH DATABASE).
How to avoid that?
I assume you mean that the GUI won't redraw itself when executing a long-running operation. (Shouldn't actually be that visible starting with Vista, but I digress).
If your long-running operation is composed of several steps or tight loops, then you can sprinkle a call to DoEvents every once in a while to cause the form to remain somewhat responsive even when doing work.
Another option would be to migrate your long-running work into a separate thread but last I looked this wasn't exactly trivial or easily possible in VB6.
You should work with data base in separate thread, and any time-consuming operation should be run in a separate thread too. In this case your user interface won't be frozen.
I posted this as an answer to another question, but the pattern applies here as well:
VB6, on its own, is single threaded. However, you can make it somewhat multithreaded via the use of ActiveX EXE that run in their own process, yet still are tethered to the original VB6-created EXE.
What I've used in the past is the Timer object in conjunction with an ActiveX EXE. This approach will give you an ability to localize all the downloading logic in one place, control it like you control a regular object and have it run in a separate EXE, thus by default making it multi-threaded.
So the way this works is like so:
You call the LongRunningOperation method on the ActiveX EXE object
In the LongRunningOperation method, you instantiate the Timer and have it kick off almost immediately.
You get out of the LongRunningOperation method, thus giving control back to the entity that called it.
Then you communicate back to the main app via Events (e.g. LongRunningOperationProgress or LongRunningOperationComplete, etc...)
I recommend the Timer object from Karl Petersen.
This is actually the same problem as your "How to exit the program immediately" question. In both cases, the problem is that your database operation is blocking the VB6 program from executing.
The answer you accepted for the other question - use ADO to carry out the operations asynchronously - will also solve this blank screen problem.
Or if you prefer, follow one of my suggestions in my answer to your other question and use a .NET background worker component through Interop like this.
Or follow my other suggestion and delegate the database work to an ActiveX exe like this. EDIT AngryHacker's nice answer to this question uses this method.
Your first instinct should be to put your resource-intensive operations in a separate thread. This is a bit difficult in VB6, although possible (but not recommended) if you invoke the native CreateThread API.
You can also migrate to VB.NET, and use Thread objects natively.
Is it possible to create an "application group" which would run under one window, but in separate processes, like in Chrome browser? I'd like to divide one application into multiple parts, so that one crashing or jamming process cannot take down others, but still keep the look and feel as close to original system as possible.
I know the Chrome source is available, but is there anything even half ready made for Delphi?
I guess basically you would create multiple processes each of which creates a window/form. One of the processes has the master window in which every child window is embedded. That is as simple as calling SetParent. The windows in different processes would talk to each other using an IPC (Inter Process Communication) mechanism like named pipes or window messages.
See this question for an embedding example of using SetParent in Delphi. See this question for an example of using named pipes in Delphi.
Have a look at the Delphi code of HeidiSQL. It's a great open source MySQL client that implements this mechanism.
Read this newsitem that was posted when Chrome was released:
"Google playing catch-up with HeidiSQL?"
:-)
(source: heidisql.com)
Have a look at : http://blogs.microsoft.co.il/blogs/maxim/archive/2008/09/23/curiosity-killed-the-programmer-multiprocess-browser.aspx . The source of the app is in CSharp. I'm sure you can adapt it to Delphi.
Harriv, you can use a scheme based on plugins. where you have a main application and this dynamically load news functionality. There are several libraries available here I leave some.
(source: wikimedia.org)
Frameworks
TMS Plugin Framework
TJvPluginManager from JVCL
Delphi Plugin Framework
Hydra
Tutorials
Implementing Plug-Ins for Your Delphi Applications
How to make a Plugin for Your Application (Source Code)
Bye.
You can separate your application logic and execute it in several threads. That way, if one part of your application logic hangs up, you still have a responsive application. But you won't be able to put the GUI in multiple threads. The VCL requires you to execute all GUI related stuff in the main thread.
I am not sure about how Delphi operates but the standard procedure for multiprocess programming is forking.
You fork a new process with whatever code you want. Pass information to the forked process and let it run doing whatever it wants.
Can't explain multiprocess programming in one thread response. But look it up.
What do you do to increase startup speed (or to decrease startup time) of your Delphi app?
Other than application specific, is there a standard trick that always works?
Note: I'm not talking about fast algorithms or the likes. Only the performance increase at startup, in terms of speed.
In the project options, don't auto-create all of your forms up front. Create and free them as needed.
Try doing as little as possible in your main form's OnCreate event. Rather move some initialization to a different method and do it once the form is shown to the user. An indicator that the app is busy with a busy mouse cursor goes a long way.
Experiments done shows that if you take the exact same application and simply add a startup notification to it, users actually perceive that app as starting up faster!
Other than that you can do the usual things like exclude debug information and enable optimization in the compiler.
On top of that, don't auto create all your forms. Create them dynamically as you need them.
Well, as Argalatyr suggested I change my comment to a separate answer:
As an extension to the "don't auto create forms" answer (which will be quite effective by itself) I suggest to delay opening connections to databases, internet, COM servers and any peripheral device until you need it first.
Three things happen before your form is shown:
All 'initialization' blocks in all units are executed in "first seen" order.
All auto-created forms are created (loaded from DFM files and their OnCreate handler is called)
You main form is displayed (OnShow and OnActivate are called).
As other have pointed out, you should auto-create only small number of forms (especially if they are complicated forms with lots of component) and should not put lengthy processing in OnCreate events of those forms. If, by chance, your main form is very complicated, you should redesign it. One possibility is to split main form into multiple frames which are loaded on demand.
It's also possible that one of the initialization blocks is taking some time to execute. To verify, put a breakpoint on the first line of your program (main 'begin..end' block in the .dpr file) and start the program. All initialization block will be executed and then the breakpoint will stop the execution.
In a similar way you can step (F8) over the main program - you'll see how long it takes for each auto-created form to be created.
Display a splash screen, so people won't notice the long startup times :).
Fastest code - it's the code, that never runs. Quite obvious, really ;)
Deployment of the application can (and usually does!) happen in ways the developer may not have considered. In my experience this generates more performance issues than anyone would want.
A common bottleneck is file access - a configuration file, ini file that is required to launch the application can perform well on a developer machine, but perform abysmally in different deployment situations. Similarly, application logging can impede performance - whether for file access reasons or log file growth.
What I see so often are rich-client applications deployed in a Citrix environment, or on a shared network drive, where the infrastructure team decides that user temporary files or personal files be stored in a location that the application finds issues with, and this leads to performance or stability issues.
Another issue I often see affecting application performance is the method used to import and export data to files. Commonly in Delphi business applications I see export functions that work off DataSets - iterating and writing to file. Consider the method used to write to file, consider memory available, consider that the 'folder' being written to/read from may be local to the machine, or it may be on a remote server.
A developer may argue that these are installation issues, outside the scope of their concern. I usually see many cycles of developer analysis on this sort of issue before it is identified as an 'infrastructure issue'.
First thing to do is to clear auto
created forms list (look for Project
Options). Create forms on the fly
when needed, especially if the
application uses database connection
(datamodule) or forms that include
heavy use of controls.
Consider using form inheritance also
to decrease exe size (resource usage is mimized)
Decrease number of forms and merge similar or related functionality into single form
Put long running tasks (open database connections, connect to app server, etc) that have to be performed on startup in a thread. Any functionality that depends on these tasks are disabled until the thread is done.
It's a bit of a cheat, though. The main form comes up right away, but you're only giving the appearance of faster startup time.
Compress your executable and any dlls using something like ASPack or UPX. Decompression time is more than made up for by faster load time.
UPX was used as an example of how to load FireFox faster.
Note that there are downsides to exe compression.
This is just for the IDE, but Chris Hesick made a blog posting about increasing startup performance under the debugger.