Link to home
Start Free TrialLog in
Avatar of PIBM
PIBM

asked on

Winsock & Multithreading

I need to be able to download page using the winsock control from many place at the time, then analyse what is written on them then download another one. That mean I must use multithreading. How can I do so ?

April 9th, 22:00 US Est
I would need to know how I could create a new class that I could call, in which it would 1 download file from the web using winsock control then check what it got to download further URL. I also need to call many of them at the same time and be able to monitor the process..
ASKER CERTIFIED SOLUTION
Avatar of caraf_g
caraf_g

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of caraf_g
caraf_g

The above is simply an example, you can adapt it to suit your needs.

Don't hesitate to ask questions if anything's not clear!
PS - the code only works for VB6. I recommend you use SP3 on that.
Avatar of PIBM

ASKER

I have VB5 SP3
OK.... Knock wood.... but I think the code may actually work OK in VB5.... Only way of knowing is by giving it a go.

The cincher will be AWXB04Starter.exe; I'm not sure whether you can actually set the threading model of an ActiveX .exe to One thread Per Object in VB5. If you can, I'm hopeful that you'll be able to get this working.
Avatar of PIBM

ASKER

Currently I made my program that get the page and analyse the whole thing ..

it's like

Data = GetURL(...)
URL = Analise(Data)
DoEvents
Data = GetURL(URL)
URL = Analise(Data)
DoEvents
Data = GetURL(URL)

etc...

When I click many times on the command button it will start many at the same time, but will run the first part of the first click, stop at the doevents, do the first part of the second click, stop at do event, do the whole third one, complete the whole second one, then complete the whole first one.

Can I make them all work together with your program ?
In theory, yes. It will require a bit of work on your part though. It's merely a framework.

Anyway, see if you can get it to run in VB5. If you can, that's great. Then have a look at it and if you have any questions, just post them here and I'll try to explain.

Pino
Avatar of PIBM

ASKER

Ok. I don't think I'll have the time to do that tonight but maybe tomorrow. See you later ( Currently at school - 10:30 am for me )
Avatar of PIBM

ASKER

if you got another idea than his please tell me =)
whose? :o)
Avatar of PIBM

ASKER

anyone else who may read it.
I have not been able to run your program, I get some exceptions things

with the createthread command I've been able to create new thread but when I try to use ado to open a database VB hangs with a stack error
PIBM, you weren't trying to run the compiled applications were you? They're VB6 applications and they won't work.

Even if you're recompiling the applications, may sure you do not use binary compatibility. Recompile them with no compatibility and re-set the references of the other projects. That way you can ensure that the whole suit is compiled as and will run as "vanilla" VB5.

Hope this helps.

Otherwise, can you tell me where and when the exception occurs, it may give me an idea where VB5 and VB6 are incompatible and how to adapt the code to work for VB5.

Cheers

Pino
Hi PIBM,

Winsock Control is a multithreading component. I do not see your code here, but I'm sure that you can solve your problem using several instances of the Winsock Control. You can build a control array in run time or put communication code to a class module that ecapsulates the Winsock Control calls, and create an instance of the class for a new download task.

Welcome to http://www.vbip.com
Avatar of PIBM

ASKER

Hello Gelog.
 My program must run without user intervention and continually download data on many winsock controls at once that I create using Load Winsock(Getfreenum). The thing is if I start three request I get ...

winsock1 page 1
winsock2 page 1
winsock3 page 1
winsock3 page 2
winsock3 .......
winsock3 lastpage
winsock2 page 2
winsock2 .......
winsock2 lastpage
winsock1 page 2
winsock1 .......
winsock1 last page.

Meaning that it must wait for the latest started winsock control to finish the whole thing even if the connection is lowly used before continuing the previous process. You think that what you said would do it ?
Avatar of PIBM

ASKER

Any of you got ICQ ?
PIBM - 2452361
Avatar of PIBM

ASKER

Could I have more information about the class thing ?
Hi PIBM, who is that question directed at? If it's directed at me, sure... what do you need to know?
Avatar of PIBM

ASKER

If that can fix my problem, how do I do that ?
Avatar of PIBM

ASKER

How do I create new classes using the winsock control in it ?
Avatar of PIBM

ASKER

Edited text of question.
Avatar of PIBM

ASKER

Caraf_g I got VB6 so I'm gonna try to run your thing ( Been able to get a bit of it to work under VB5 but the ADO controls where acting strangely so it should be ok now, at least I hope !)
Avatar of PIBM

ASKER

Ok I got it to work, not flawlessly but still it works =)
Excellent! Do I deserve some points for that then?
PS - if you are thinking about giving me a grade less than "A", please don't... In that case I would prefer it if you would not accept any of my comments here and delete this question.

In that case you could however post a dummy question "for caraf_g" with less than 100 points.

Thanks

Pino
Avatar of PIBM

ASKER

Your program is working perfectly. I've been able to do everything I want with it but I don't understand everything. I've found how the messages are sent and all that stuff but I would like to know how you though of that, from where does it came =)

If you can answer a few more questions I will give you grade A ;)

Thanks a lot for everything you did up to now :)
Avatar of PIBM

ASKER

Well I'm running into some errors again. I believe this is caused by the DAO thing .. :\
Where did it come from...

1 - I had to write a multi threading application. This was a problem, as VB(6) does not support free threading. It does however support some forms of threading, and I had to investigate these.

2 - The problem with VB function calls is that all of them work synchronously. As a result, you cannot, in Native VB, create the situation where process A initiates Process B, then forgets about it, and both processes continue in parallel. At least, not if you want to avoid shelling out separate .exes. Shelling is *WAY* too slow. I wanted an ActiveX solution.
As a result, I had to investigate APIs. CreateThread is one option, but it's too quirky and too much like rocket science. Basically you cannot guarantee that a program using CreateThread will not bomb out with GPFs and similar horrible errors unless you've got a brain the size of a planet.... I quickly abandoned that idea. So the other solution is to use a Timer. I could have used a VB timer, but the API timer is a bit more elegant and it does not require you to introduce a dummy form.

3 DLLs are not usable for multi-threading. Even if you take an apartment threaded idea, each apartment will run in the same thread as the calling process. Again, there are weird and wonderful API solutions to this, but again it requires a brain the size of a planet... So forget that. I then looked at ActiveX .exes for the solution. They worked.

4 This is where I ran into a problem with the threading models supported in VB, especially with regards to global data (variables). Basically, there are two threading models in VB:
a - Thread pool. You can specify as many threads as you wish, but the problem is that every object that is created is assigned a thread "randomly". For sharing global data that is useless. So the only viable option there is to have 1 thread. Now you're OK. Every object that is created uses the *same* global data so it can be shared between the objects. But... *BANG* goes your multi-threading, because *ALL* objects run in the *SAME* thread....
b - Thread per object. Ideal for multi threading. Every object you create runs in its own thread.... but, now you can't share global data. If you have a simple application, this is no problem, as you can code everything into a single class, but if your application gets any more complex, you'll need new classes, and your model will fall apart...

So here's a dilemma.... There are two viable threading models available in my ActiveX .exe, but both have insurmountable problems. One model is useless wrt global data, the other wrt multi threading.

Solution:
5 The ActiveX.exe will only contain a SINGLE object. This object's sole function will be to cater for the multi-threading. Once that is achieved, we'll hand over execution to an Apartment Threaded DLL, which will then take care of any other classes and objects that need to be created, and it will ensure that all these new objects are all created in the *SAME* thread.

The activeX.exe is AWXB04Starter.exe , and the Apartment Threaded DLL is  AWXB01Thread.dll

Finally...
As long as execution remains synchronous, it is very easy for a called function to report back to a calling function. It merely needs to switch off error handling, and raise a user-defined error. The calling function can than handle this "error" and act appropriately.

But in asynchronous execution, that won't work. In actual fact, if you raise an error in the asynchronous bit (that which is called from the TimerProc) your ActiveX.exe will crash.

So how will the threads report back information to the calling application?

6 Introduce a Thread Pool ActiveX.exe (1 thread) that will take care of handling messages between the thread(s) and the calling application.
This ActiveX.exe is AWXB02MSG.exe



I don't know about your DAO errors. If they're unhandled errors they might be causing the problem described before point 6, in which case you can sort that by making sure your error handling is capable of catching all errors.

You can introduce a special message in your messaging .exe to report back fatal errors to the calling application, so that it knows one of its threads has died on it.

You can also introduce messages that are sent from the Calling application to one of the threads.

I don't know about your DAO problems, if they're DAO specific they're outside the scope of this question. I hope you'll sort them.

Hope this helps

Pino
Avatar of PIBM

ASKER

Thanks a lot, that answer most of my problem. I believe the problem with the DAO driver is when two threads try to write on the database at the same time. Why do I think this is the error - I never get the error with less than 4 thread runnings .. as many thread I have as faster I run into the bug. Not a memory problem because one of the part never write in the database and I can run easily 30 of them at the same time.

I don't know how I'll do to handle the error but I'll see. I can't trace this error in VB since if I run the DLL it won't create new threads.

Also I had a new kind of error - Unknown Bookmark???

I'll check that out tonight. Should I give you your points right now ? :)
Avatar of PIBM

ASKER

Oh yeah when I create the threads I use a system where the first letter is the type of Form that will be loaded and the following is only for future reference. That give us the possibility to code a lot of things in the same DLL, use the same module for all the functions and stuff like this, that's perfect for this :)

The only thing I can't include somewhere else than on the form is the Database access. Could I create the database access code in the messaging active x, that would use only one connection so there could be no problem with it ?

in the form I use it like this..
form load ...
 dim db as database
 dim rs as recordset

 set db = workspaces(0).opendatabase(...

commandX.click
 set rs = db.openrecordset(SQLCommand)
 ...
 rs.close
 set rs = nothing

form unload
 db.close
 set db = nothing

So if I use the obj of  AWXB02MSG in which I could include a procedure to get the recordset ( like Public Function GetRS(SqlCommand as string) as Recordset ), would that work ?

Just an idea I had :)
Avatar of PIBM

ASKER

Adjusted points from 100 to 150
"messaging active x, that would use only one connection so there could be no problem with it"

Yes, that might work. Well, give it a try!
Avatar of PIBM

ASKER

That's what I'll do tonight. I should post again tomorrow about any question I might have. If it works perfectly I'll just give you your points =)

And grade A ;)