Safe Multithreading in VB6 (CreateThread discussion)

Sivvy
02-04-2006, 06:01 PM
Hey all

It's been a long day and I've been all over, but let me tell you what I've found...

I read, understood and tested everything Daniel Appleman had to say in his article about multithreading in VB (http://www.desaware.com/tech/threading.aspx). Unfortunately the method he provided (marshalling/activex exe) doesn't work for VB6 (it works in the IDE, but compiled it always crashes, something Daniel failed to mention till the reader reaches the bottom of the article... and then he refers to a $500 spyworks code collection he made, :rolleyes:).

Then I went to pscode (usually messy code, but often good ideas), and found that several people have tried to pursue multithreading in VB6 as well. Unfortunately, they all rely on the CreateThread API, which doesn't allow I/O operations in the new thread (something which I and undoubtably a whole lot of others would love to be able to do).

I have to mention one exception on pscode, by a certain Srideep Prasad, who also uses CreateThread, but makes it more safe using various hacks and most importantly: adds support for I/O operations. Link to the project (http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=26900&lngWId=1). Unfortunately the method is still way to unstable (frequent crashes, and hardly anything more fancy than a for each...next works).

On vbforums.com a certain 'woka' came up with one more solution: simulate multithreading by using timers to switch between tasks. Obviously this is much slower than real mulithreading (because the more threads the app has the more CPU time it gets, and with timers it still only has 1 thread).

Right now, I don't no where to go. If someone could refer me to a more definite reference (books,sites,anything) that would be great. I refuse to believe it's not possible to *safely* create a multithreaded VB6 application. It was possible in VB5 so it should also be possible in VB6.

Sivvy

dilettante
02-04-2006, 06:17 PM
Maybe stating a more specific goal might be useful in garnering suggestions.

You've clearly explored the more obvious routes for generalized VB multithreading and run across the limitations. Not every problem that one might need several execution paths for requires such generality.

Sivvy
02-04-2006, 06:34 PM
Maybe stating a more specific goal might be useful in garnering suggestions.

You've clearly explored the more obvious routes for generalized VB multithreading and run across the limitations. Not every problem that one might need several execution paths for requires such generality.

Well my goal would be to be able to create a multithreaded project (not a simulation) that doesn't crash at every turn and that supports I/O operations properly (something I really need to get to work).

By the way, I also saw the EliteVB code sample which was (re)posted on this forum, and it turns out the pscode demo project I refered to in my previous post is an improved version of that, because the EliteVB one has no support for I/O whatsoever (the pscode version has minimal support for I/O).

reboot
02-04-2006, 07:25 PM
If you really need a multi-threaded app, why not move to .Net?

dilettante
02-04-2006, 09:14 PM
I assume you've looked at things like http://www.vbaccelerator.com/home/VB/Code/Libraries/Threading/Multi-threading_using_classes_in_ActiveX_EXEs/article.asp

dilettante
02-04-2006, 09:23 PM
I'm also curious about these I/O operations you want to perform.

Is this all about performing blocking I/O calls on a separate thread instead of using async I/O operations or what?

You want "more CPU time." I don't have a clue how multithreading buys you that. If anything I'd think the overhead results in a net loss unless you are running in an SMP (or near-SMP e.g. multicore, hyperthreaded) machine.

Sivvy
02-05-2006, 02:26 AM
I'm also curious about these I/O operations you want to perform.

Is this all about performing blocking I/O calls on a separate thread instead of using async I/O operations or what?

You want "more CPU time." I don't have a clue how multithreading buys you that. If anything I'd think the overhead results in a net loss unless you are running in an SMP (or near-SMP e.g. multicore, hyperthreaded) machine.

I've looked at the ActiveX EXE method before, and although it works, there are two things I don't like about it: a) another exe and more importantly b) it is not suitable if large amounts of data is ment to be sent back and forth between the two exes.

The I/O operations I ment are actually as simple as they can get: open files, read out data and store them in byte arrays, then process them. The problem is, the 'Open' statement and a whole lot of other statements always crash a CreateThread multithreaded project.

I ment more CPU time relatively. The thing is, I/O is not the only thing I'm trying to do with multithreading, I'm also using a few API's to capture input devices (e.g. recording sound from the mic). If the app only has one thread and if it simulates multithreading using timers, then the CPU time the one thread gets is going to get divided between the tasks in the app. If the app had more than one thread, then each thread would get its own CPU time, thus relatively increasing performance. Don't get me wrong, I'm not a performance freak, stability goes first.

Wouldn't it be possible to adapt Daniel Applemans apartment model/active x method for VB6? He mentioned at the bottom of his page you would need to 'remove the Declares' and 'add a reference to a tlb'. That doesn't mean anything to me, but perhaps others might recognize what needs to be done.

Sivvy
02-05-2006, 03:36 AM
If you really need a multi-threaded app, why not move to .Net?

Indeed, if there is no solution to this problem I would be very disappointed and I would probably move to another language.

I probably wouldn't move to VB.NET however, because although I think VB6 is great, it will always be a more or less 'limited' language to me. I'd probably go for Visual C++, and although the learning curve may be steeper, the reward will most likely be greater in the end.

First things first though, this discussion isn't over yet :p! It may very well be possible to multithread VB6 apps, because Daniel Appleman hints his Spyworks collection has the ability to do so (unfortunately it's a little too expensive for me to buy, just to get multithreading to work).

dilettante
02-05-2006, 09:43 AM
Well I don't want to let the ActiveX EXE method go just yet for a couple of reasons:

Is is the native way to multitask in VB.
It doesn't not require any potentially crash-causing tricks that wiggle around the threading model used by VB.
It may well be of value to others reading this thread even if it won't meet your needs.


By the way, you're wrong about one thing: it doesn't mean a second EXE. The attached demo illustrates that quite nicely. I use this technique for lots of things including a custom multiuser remote shell service. Be sure to read the short ReadMe.txt if you want to build and test the demo out. I should add that you can't run this one within the IDE.

The VB6 documentation covers this type of solution as well as another threading solution using ActiveX EXEs in a different way.


While you have a point about the cost of marshalling large amounts of data back and forth between a calling program and an out of process COM object a lot of applications don't have this problem. If you're going to have a second (third, etc.) thread in the first place why not make it do some work and not just be a dumb I/O engine?

This is the classical problem of n-tiered client/server development. In such cases the intervening network only amplifies the cost of passing a lot of data between "layers." As a result it is usually most efficient to process bulk data where it lives and only pass more condensed results from processing between tiers.

I didn't entirely optimize my quicky demo for this. It could be improved by eliminating some data copying that is going on (using ByRef instead of ByVal in a few places would accomplish some of this).


Please keep in mind that I'm not knocking what you want to do. I'm just suggesting you might take another look at your solution and see whether or not you could move some of the crunching into worker threads - instead of shuffling large volumes of data around or dumping it into globals.

In lots of applications the Master thread of execution is really just a user interface or coordinator and shouldn't really be touching vast amounts of raw data anyway. Of course your requirements may mean you need something more drastic.

dilettante
02-05-2006, 10:02 AM
Sivvy, rereading your more recent posts makes me think you may indeed need multiple "threads" of execution.

Clearly keeping your "control panel" responsive while gathering a stream of digitized audio would be important. If there were proper components available to do async captures and async I/O you might not need threads, but then again it might still be the best way to handle things.

If you look at the demo I posted you might find that it could be adapted for your needs though. Instead of a single "Process my request" method you might want several. This would let you keep and process bulk data over in the Slave process(es). Some methods to "interrupt" the Slave could be used as well to signal stuff like "stop recording."

In truth I haven't tried this though... perhaps it wouldn't work properly to have a class method Stop that set a Boolean variable Stop that is monitored by the loop doing the hard work.


Good luck in your quest. I suspect you'll find that true multithreading in VB isn't worth the effort and probably isn't stable, even with Appleman's $$ helper software.

I'm trying to remember... wasn't Appleman's TLB story all about making global data visible among all of his "threads?"

Oops:

The TLB he recommends is a way to access DLL entrypoints without using VB Declare statements. I have to wonder though how it addresses the concerns he raised.

Sivvy
02-06-2006, 07:23 AM
Sivvy, rereading your more recent posts makes me think you may indeed need multiple "threads" of execution.

Clearly keeping your "control panel" responsive while gathering a stream of digitized audio would be important. If there were proper components available to do async captures and async I/O you might not need threads, but then again it might still be the best way to handle things.

...


It should indeed be possible to use the ActiveX exes as the main 'engine' and reserve the GUI for being the 'shell'. However, this method raises the need for a different programming approach, which imho will probably result in roughly the same amount of work as just learning C++.

For future reference (for others reading this thread), it is advisable to use the ActiveX exe multithreading method (see Dilletantes attachment for a demo), as it is the only stable *and* fully functional way that I've come across (unless you count in the 'simulation' method, which is rather slow).

EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum