Quick Search for:  in language:    
ICQ,article,going,many,other,commands,with,Vi
   Code/Articles » |  Newest/Best » |  Community » |  Jobs » |  Other » |  Goto » | 
CategoriesSearch Newest CodeCoding ContestCode of the DayAsk A ProJobsUpload
Visual Basic Stats

 Code: 3,011,557. lines
 Jobs: 115. postings

 How to support the site

 
Sponsored by:

 

You are in:

 
Login



Latest Code Ticker for Visual Basic.
Locate Database
By Erica Ziegler-Roberts on 6/30


Organize the errors of your programs
By Toni on 6/30


how to open and close access database
By Freebug on 6/29


Click here to see a screenshot of this code!PSC-Browser
By Ralph LONG Metz on 6/29

(Screen Shot)

Click here to see a screenshot of this code!Quadratic Solver 2
By Guillaume Couture-Levesqu e on 6/29

(Screen Shot)

Click here to see a screenshot of this code!Array Example
By Cold Fire on 6/29

(Screen Shot)

Click here to see a screenshot of this code!Reconstructor 3.0
By Peter Scale on 6/29

(Screen Shot)

Click here to see a screenshot of this code!Subtitles Manager
By KarahaNa on 6/29

(Screen Shot)

XPlorer
By ZProse on 6/29


Click here to put this ticker on your site!


Add this ticker to your desktop!


Daily Code Email
To join the 'Code of the Day' Mailing List click here!





Affiliate Sites



 
 
   

API - Simulate multithreading with WaitForMultipleObjects (eg. How ICQ monitors connection state)

Print
Email
 

Submitted on: 5/19/2002 9:40:18 AM
By: <b>John Galanopoulos</b> 
Level: Intermediate
User Rating: By 32 Users
Compatibility:VB 4.0 (32-bit), VB 5.0, VB 6.0, VB Script, ASP (Active Server Pages) , VBA MS Access, VBA MS Excel

Users have accessed this article 6918 times.
 

(About the author)
 
     In this article, we are going to see how to use WaitForSingleObject, WaitForMultipleObjects, RasConnectionNotification and many other commands with Visual Basic. We are also going to see how to monitor multiple events without the need of multithreading. I have included two examples : how to monitor when a shelled application has ended and how ICQ monitors connection state (that little flower that gets green when we dial-up and establish a connection). If you like it, post a comment. I ll be happy to read your thoughts or suggestions. (****** A Special "Thank you" goes to all of you who spent a few secs to rate this article :)

This article has accompanying files
 
 
Terms of Agreement:   
By using this article, you agree to the following terms...   
1) You may use this article in your own programs (and may compile it into a program and distribute it in compiled format for languages that allow it) freely and with no charge.   
2) You MAY NOT redistribute this article (for example to a web site) without written permission from the original author. Failure to do so is a violation of copyright laws.   
3) You may link to this article from another website, but ONLY if it is not wrapped in a frame. 
4) You will abide by any additional copyright restrictions which the author may have placed in the article or article's description.
Simulate multithreading with WaitForMultipleObjects

Simulate multithreading with WaitForMultipleObjects 

               (eg. How ICQ monitors connection state)

I have used extensivly the event driven mechanism that Windows provide in many different programming aspects

(RDO, ADO, ODBC, Windows Sockets, Winlogon, mutexes, semaphores etc) and used WaitForSingleObject when

i was in need of an event monitor API command. 

 

The WaitForSingleObject is located in kernel32.dll and waits until a specific event objects gets signaled or when a time limit is

reached. It accepts two parameters; a handle to the event object and a time-out interval. 

 

** The main benefit of this function is that it uses no processor time while waiting for the object state 

to become signaled or the time-out interval to elapse.

 

Here is the declaration :

 

Public Declare Function WaitForSingleObject Lib "kernel32" Alias "WaitForSingleObject" _

(ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long

Let's see an example of this command's usage :

 

In this example we are going to run the Windows calculator.

We will open this shelled process and we will monitor the process handle; 

if it gets 0 then the process was ended.

 

Public Const WAIT_FAILED = &HFFFFFFFF;               'Our WaitForSingleObject failed to wait and returned -1
Public Const WAIT_OBJECT_0 = &H0;&                        'The waitable object got signaled '
Public Const WAIT_ABANDONED = &H80;&                'We got out of the waitable object
Public Const WAIT_TIMEOUT = &H102;&                      'the interval we used, timed out.
Public Const STANDARD_RIGHTS_ALL = &H1F0000;  'No special user rights needed to open t ' his process

Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Public Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Public Sub ShelledAPP()
Dim
shProcID As Long
Dim
hProcess As Long
Dim
WaitRet As Long

shProcID = Shell("calc.exe", vbNormalFocus)
hProcess = OpenProcess(STANDARD_RIGHTS_ALL, False, shProcID)

'This is the proper and optimized way to ' use the WaitForSingleObject function. 


'I saw many programmers use the INFINITE constant as for the dwMilliseconds field. 

'If dwMilliseconds is INFINITE, the function's time-out interval never elapses.

'That's wrong 'cause the program won't refresh thus giving the impression that is a hung application.

'In Windows XP specially you might see a popup screen informing you about this.

'The problem also appears when you apply WaitForSingleObject with INFINITE in an application that

'uses windows. 

'Always use a reasonable number of milliseconds and always use DoEvents to refresh the program's message queue

 Do  
  
WaitRet = WaitForSingleObject(hProcess, 10)   ' wait for 10ms to see if the hProcess was signaled
           Select Case
WaitRet
  

                    Case WAIT_TIMEOUT   'The first case must always be WAIT_TIMEOUT 'cause it is the most used option
                             
DoEvents                'until the shelled process terminates 

                    
                    Case
WAIT_FAILED or WAIT_ABANDONED
                             
MsgBox "Wait failed or abandoned"
                              Exit Do

                    Case
WAIT_OBJECT_0 'The object got signaled so inform user and get out of the loop
                            
MsgBox "The shelled application has ended"
                             Exit Do

          End Select
 Loop

Call CloseHandle(hProcess)     'Close the process handle
Call
CloseHandle(shProcID)    'Close the process id handle

DoEvents       'free any pending messages from the message queue


End Sub


Now what if we had to monitor two or more shelled applications? are we going to use multithreading?

I haven't yet implemented multithreading api in a vb.net project of mine but as you most know, 

multithreading is lethal (basically for those who will implement the CreateThread API function) when used within Visual Basic 6 (or prior).

Crashes, unexpected terminations, exceptions and many other "beautifull" encounters are some of the experiences a programmer can get.

 

The answer comes from WaitForMultipleObjects API function which is also included in kernel32.dll

Here is the declaration :

 

Public Declare Function WaitForMultipleObjects Lib "kernel32" Alias "WaitForMultipleObjects" (ByVal nCount As Long, lpHandles As Long, ByVal bWaitAll As Long, ByVal dwMilliseconds As Long) As Long

it accepts four values :

nCount as the maximum number of events to monitor,

lpHandles as the array of different event handles (not multiple copies of the same one),

bWaitAll  (True/False) True if it must return when the state of all objects is signaled,

                                   False if it must return when the state of any one of these objects gets signaled,

dwMilliseconds as a maximum time-out interval

 

Like WaitForSingleObject, WaitForMultipleObjects can accept event handles of any of the following object types 

in the lpHandles : Change notification, Console input, Waitable timmer, Event, Job, Mutex, Process, Semaphore

and Threads

 

In the following example we are going to try something else than monitoring multiple shelled apps; 

Those of you that have ICQ installed, have noticed that "red flower" icon, placed on the system tray.

When you are not connected on the internet, ICQ makes this icon look like inactive.

Now when you connect, it suddently starts to get one by one of it's leaf green, meaning that it tries to

connect to it's main server and when the connection completes, the flower get's green.

 

How do they do it? I mean. do they have an IsConnected() function on a timer with some interval?

Definetly no!

What they do is take advantage of WaitForMultipleObjects with another function located in rasapi32.dll; RasConnectionNotification 

 

The RasConnectionNotification function specifies an event object that the system sets to the signaled state when 

a RAS connection is created or terminated.

The function accepts three values :


hrasconn as the handle to a RAS connection 

hEvent  as the  handle to an event object 

dwFlags as the type of event to receive notifications for (RASCN_Connection or RASCN_Disconnection)

 

Now we are going to use WaitForMultipleObjects  to monitor both events

 

 

Public Const RASCN_Connection = &H1;       'Our two flags
Public Const RASCN_Disconnection = &H2;

Public Const WAIT_FAILED = &HFFFFFFFF;
Public Const WAIT_OBJECT_0 = &H0;&
Public Const WAIT_ABANDONED = &H80;&
Public Const WAIT_TIMEOUT = &H102;&

Public Type SECURITY_ATTRIBUTES
          nLength As Long
          lpSecurityDescriptor As Long
          bInheritHandle As Long
End Type

Public Declare Function CreateEvent Lib "kernel32" Alias "CreateEventA" (lpEventAttributes As SECURITY_ATTRIBUTES, ByVal bManualReset As Long, ByVal bInitialState As Long, ByVal lpName As String) As Long
Public Declare Function RasConnectionNotification Lib "rasapi32.dll" Alias "RasConnectionNotificationA" (hRasConn As Long, ByVal hEvent As Long, ByVal dwFlags As Long) As Long
Public Declare Function WaitForMultipleObjects Lib "kernel32" (ByVal nCount As Long, lpHandles As Long, ByVal bWaitAll As Long, ByVal dwMilliseconds As Long) As Long
Public Declare Function ResetEvent Lib "kernel32" (ByVal hEvent As Long) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

 

Public Sub MonitorRASStatusAsync()

Dim hEvents(1) As Long        'Array of event handles. Since there are ' two events we'd like to monitor, i have already dimention it.
Dim RasNotif As Long          
Dim WaitRet As Long           
Dim sd As SECURITY_ATTRIBUTES
Dim hRasConn As Long

hRasConn = 0

'We are going to create and register two event objects with CreateEvent API function

'There aren't any special treated events that need any kind of security attributes so we just initialize the structure

 

With sd                                
       .nLength = Len(sd)      'we pass the length of sd 
       .lpSecurityDescriptor = 0
       .bInheritHandle = 0
End With

'We create the event by passing in CreateEvent any security attributes, 

'we want to manually reset the event after it gets signaled,

'we also want it's initial state not signaled assuming that we don't have yet any connection to the internet,

'last but not least we give the event a name (RASStatusNotificationObject1)
hEvents(0) = CreateEvent(sd, True, False, "RASStatusNotificationObject1")
'If the returned value was zero, something went wrong so exit the sub

If hEvents(0) = 0 Then MsgBox "Couldn't assign an event handle": Exit Sub

'If we succesfully created the first event object we pass it to RasConnectionNotification

'with the flag RASCN_Connection so that this event will monitor for internet connection

RasNotif = RasConnectionNotification(ByVal hRasConn, hEvents(0), RASCN_Connection)
If RasNotif <> 0 Then MsgBox "Ras Notification failure": GoTo ras_TerminateEvent


'We create the second event object exactly like the first one

'but we name it RASStatusNotificationObject2

hEvents(1) = CreateEvent(sd, True, False, "RASStatusNotificationObject2")
If hEvents(1) = 0 Then MsgBox "Couldn't assign an event handle": Exit Sub

'If we succesfully created the second event object too, we pass it to RasConnectionNotification

'with the flag RASCN_Disconnection. This event will monitor for disconnection

RasNotif = RasConnectionNotification(ByVal hRasConn, hEvents(1), RASCN_Disconnection)
If RasNotif <> 0 Then MsgBox "Ras Notification failure": GoTo ras_TerminateEvent

'We then issue the loop

'Notice that we have put hEvents array to it's first array item.

'and we used False cause we want to get notifications

'when any of the two events occur.
 Do
       WaitRet = WaitForMultipleObjects(2, hEvents(0), False, 20)
                       Select Case WaitRet
                                 Case WAIT_TIMEOUT
                                          DoEvents

                                 Case WAIT_FAILED Or WAIT_ABANDONED Or WAIT_ABANDONED  + 1
                                          GoTo ras_TerminateEvent

                                 Case WAIT_OBJECT_0
                                           MsgBox "Connected"
                                           ResetEvent hEvents(0) 'Reset the event to avoid a second message box 
                                           DoEvents    'Free any pending messages

                                 Case WAIT_OBJECT_0 + 1 
                                          MsgBox "Disconnected"
                                          ResetEvent hEvents(1) 'Reset the event to place it in no signal state (Manual reset, remember?)
                                          DoEvents 

                        End Select
                  
  Loop

ras_TerminateEvent:

'Close all event handles

'For more than two events you could apply  a For.. Next

Call CloseHandle(hEvents(1))     
Call CloseHandle(hEvents(0))

DoEvents    'Free any pending messages from the application message queue


End Sub


Now imagine that you could monitor events from different objects like

a file or folder change, along with connection status, shelled applications,

multiple printer objects, different processes and threads etc etc etc.

(64 maximum event objects i think)

 

It will appear that you program is multithreading but the truth behind that, is

that you will be taking advantage of WaitForMultipleObjects internal

multithreading mechanism.

 

I hope i helped with this article, people.

Feel free to leave any comments or suggestions.

It will help all of us.

 

John Galanopoulos

winzip iconDownload article

Note: Due to the size or complexity of this submission, the author has submitted it as a .zip file to shorten your download time. Afterdownloading it, you will need a program like Winzipto decompress it.

Virus note:All files are scanned once-a-day by Planet Source Code for viruses,but new viruses come out every day, so no prevention program can catch 100% of them.

FOR YOUR OWN SAFETY, PLEASE:
1)Re-scan downloaded files using your personal virus checker before using it.
2)NEVER, EVER run compiled files (.exe's, .ocx's, .dll's etc.)--only run source code.
3)Scan the source code with Minnow's Project Scanner

If you don't have a virus scanner, you can get one at many places on the net including:McAfee.com

 
Terms of Agreement:   
By using this article, you agree to the following terms...   
1) You may use this article in your own programs (and may compile it into a program and distribute it in compiled format for languages that allow it) freely and with no charge.   
2) You MAY NOT redistribute this article (for example to a web site) without written permission from the original author. Failure to do so is a violation of copyright laws.   
3) You may link to this article from another website, but ONLY if it is not wrapped in a frame. 
4) You will abide by any additional copyright restrictions which the author may have placed in the article or article's description.


Other 8 submission(s) by this author

 

 
Report Bad Submission
Use this form to notify us if this entry should be deleted (i.e contains no code, is a virus, etc.).
Reason:
 
Your Vote!

What do you think of this article(in the Intermediate category)?
(The article with your highest vote will win this month's coding contest!)
Excellent  Good  Average  Below Average  Poor See Voting Log
 
Other User Comments
5/19/2002 10:55:00 AM:Phillip O'Neal
Thanks for the article, really usefull. Could you show a sample code that monitor files, folders and drives if that can be done? Thanks again, Phillip
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
5/19/2002 11:14:55 AM:Mike
Man this article deserves 100.Perfect man. Is there any project file with the source?
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
5/19/2002 12:05:49 PM:Cypher
Awesome documentation, would be nice to have a project sample like Mike said...
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
5/19/2002 1:16:02 PM:Arcangel_99
Yeah ditto I would like to see a Multi Channel Chat room made with this... like IRC, ICQ, Yahoo, MSN ect.. 5 globes from me
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
5/19/2002 1:18:57 PM:MrBobo
Very impressive John. Clear and easy to understand. I dont think it needs a sample project, but I suppose it wouldn't hurt. Those building a project with this code should remember to put some sort of Flag in their unload event to exit any loops. Excellent code, wish there were more submissions like this - 5 little round green things from me!
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
5/20/2002 2:29:04 AM:Al
My friend, you are truly amazing. Bravo Giannare, apsogos. 5 from me. Keep up
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
5/20/2002 12:29:19 PM:John Galanopoulos
Thank you all of you guys. It feels superb knowing that you are offering something to the community. I promise when i find some time to create such project.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
5/20/2002 1:52:50 PM:Carlos
Bravo ! Formidable :)
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
5/20/2002 4:24:46 PM:J. M. Rizzo
Great article. It is great to see an article on PSC that is clearly demonstrated and presented so clearly. You get a 5 from me.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
5/21/2002 3:36:12 AM:John Galanopoulos
Thanx Carlos and Rizzo.. Thanks for your support.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
5/21/2002 5:49:36 PM:Ozan Yasin Dogan
I think that doevents is not a good methode for keeping a programme running healtly and it uses a good quantity of CPU. I think it will be better to do it with a timer.. Perhaps, nice explanation ! 5 by me.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
5/22/2002 7:02:06 AM:John Galanopoulos
Thank you Ozan
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
5/23/2002 3:21:35 PM:Lefteris Eleftheriades
Excellent!!!
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
5/24/2002 3:38:03 PM:John Galanopoulos
George and Trevor, you may repost your comments if you like ;)
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
6/5/2002 6:48:42 PM:Jure
Great job John, trully great. U helped me a lot! thanks
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
8/13/2002 11:05:44 AM:Javier
Excelent article!. Very helpful. But it doesn't detect internet conection on a LAN. I'd like to do something similar on a LAN connection.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
8/16/2002 2:58:02 PM:Charles Geach
I don't quite get it: yes the code as presented will wait for the connection, but you have to be in a VB loop to get any feedback. So if I want my app to be notified when a connection is made, I have to use some sort of timer anyway, and also if my timer misses the connection event, I will never see it? Maybe I'm missing something? Please let me know? Thanks cgeach@eyecaresoftware.co m
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
8/16/2002 3:02:30 PM:John Galanopoulos
That's what WaitForMultipleObjects does. You don't need a timer. It just sits in the background waiting for the connection event to occur. Not timers no nothing.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
8/29/2002 4:08:55 AM:puppinoo
Great article and excellently commented! Thanks!
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
3/29/2003 9:28:32 AM:Vasilis Ioannidis
Great work! Poly kalh douleia J! Mono pou den mporw na katalabw giati ayto mou epistrefei panta -1 WaitRet = WaitForMultipleObjects(2, hEvents(0), False, 20) Anyway thx! Keep this articles coming.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
3/29/2003 9:38:35 AM:Vasilis Ioannidis
5 globes from me also! ;)
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/9/2003 2:21:27 AM:Russell
This was a very clearly written and extremely helpful article Thank you for sharing
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
5/28/2003 9:53:51 PM:
Very Good Article ! I use these API calls day in and day out. You have done a good job explaining it. BTW, if anyone is iterested, my company makes a great VB6 Multi-Threading that allows programmers to create true multithreaded VB6 applications, components and controls.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
Add Your Feedback!
Note:Not only will your feedback be posted, but an email will be sent to the code's author in your name.

NOTICE: The author of this article has been kind enough to share it with you.  If you have a criticism, please state it politely or it will be deleted.

For feedback not related to this particular article, please click here.
 
Name:
Comment:

 

Categories | Articles and Tutorials | Advanced Search | Recommended Reading | Upload | Newest Code | Code of the Month | Code of the Day | All Time Hall of Fame | Coding Contest | Search for a job | Post a Job | Ask a Pro Discussion Forum | Live Chat | Feedback | Customize | Visual Basic Home | Site Home | Other Sites | About the Site | Feedback | Link to the Site | Awards | Advertising | Privacy

Copyright© 1997 by Exhedra Solutions, Inc. All Rights Reserved.  By using this site you agree to its Terms and Conditions.  Planet Source Code (tm) and the phrase "Dream It. Code It" (tm) are trademarks of Exhedra Solutions, Inc.