dcsimg
Page 2 of 2 FirstFirst 12
Results 41 to 61 of 61

Thread: [ADVANCED] Multi-threaded VB6

  1. #41
    Frenzied Member wqweto's Avatar
    Join Date
    May 2011
    Posts
    1,365

    Re: [ADVANCED] Multi-threaded VB6

    @qvb6: SendMessage *has* to switch threads as its synchronous by definition. PostMessage just appends to hWnd's message queue and returns (no thread switching). Subsequently the OS takes care this message queue to get "emptied" on the "correct" thread by the "correct" message pump -- remember that each thread has to have a separate msg pump, right?

    cheers,
    </wqw>

  2. #42

    Thread Starter
    Member
    Join Date
    Apr 2015
    Posts
    35

    Re: [ADVANCED] Multi-threaded VB6

    Looks promising, do you have the dim for WM_ID_ASYNCH_METHOD, cant find it anywhere...

  3. #43

    Thread Starter
    Member
    Join Date
    Apr 2015
    Posts
    35

    Re: [ADVANCED] Multi-threaded VB6

    What do we think about passing the main thread form hWnd to the worker thread and using SetTimer for async notification? LOL

    It appears to be entering on the main ThreadID

    PostMessage looks better if I can figure out how to receive the event.
    Last edited by PsuFan; May 14th, 2019 at 02:36 PM.

  4. #44
    Hyperactive Member
    Join Date
    Feb 2019
    Posts
    306

    Re: [ADVANCED] Multi-threaded VB6

    Quote Originally Posted by PsuFan View Post
    PostMessage looks better if I can figure out how to receive the event.
    DoEvents.

  5. #45

    Thread Starter
    Member
    Join Date
    Apr 2015
    Posts
    35

    Re: [ADVANCED] Multi-threaded VB6

    Looks like you have to sub-class form in order to receive Send/PostMessage events. Should work well in combination with shared memory thread / recordset / shared memory address.

    Code:
    Private Sub Form_Load()
    lngOldWindowProc = SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf NewWindowProc)
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
    SetWindowLong Me.hwnd, GWL_WNDPROC, lngOldWindowProc
    End Sub
    
    ' IN MODULE
    
    Public Function NewWindowProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        Select Case Msg
            Case USR_MESSAGE1
                'Debug.Print wParam
                NewWindowProc = 0
            Case Else
                NewWindowProc = CallWindowProc(lngOldWindowProc, hwnd, Msg, wParam, lParam)
        End Select
    End Function

  6. #46
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    5,482

    Re: [ADVANCED] Multi-threaded VB6

    I'm going to try and make a single post to this thread. I've been watching it, and I've also gone down the road of multi-threading-for-VB6 a couple of times in the past. I've come up with what I thought were good approaches to multi-threading, but I've never found anything that I'd feel good enough about to put into production.

    Also, along the way, I learned that there's the hierarchy of process, thread, & fiber. I suppose you could even work more into that hierarchy. You could certainly put core above process.

    However, because of all the marshaling issues, I decided that if/when I need something like this, I'm just going to write an entirely new VB6 application (a new process). This accomplishes a few things. First, it puts me back into the possibility of being portable. Second, it brings me back to ground on which I feel extremely solid. Third, I can still do inter-process memory copying similar to marshaled-shared memory (but not exactly because memory is copied and not shared).

    If I don't want a user to execute this second process, I can just put some command line flag on it. And, I'll just do all my inter-process communications with SendMessageTimeout and WM_COPYDATA, and a subclassed window in the receiving process. I've got it all setup, and there's no problem going both directions. If someone wants, I'll post my subclassing and send message code.

    Y'all Take Care,
    Elroy
    Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.

  7. #47

    Thread Starter
    Member
    Join Date
    Apr 2015
    Posts
    35

    Re: [ADVANCED] Multi-threaded VB6

    Elroy,

    That's exactly what I WAS doing. I had a GUI ActiveX application and a Service application that did backend work. It relays information via Referenced COM. But it became a pain to debug because I have to compile the GUI so that the service can interact via COM. Once I found out that you can do multi-thread in VB6, I figured eliminating the other process would tidy up a lot. There's a lot of send/receive code between processes for each function requiring data.

  8. #48

    Thread Starter
    Member
    Join Date
    Apr 2015
    Posts
    35

    Re: [ADVANCED] Multi-threaded VB6

    ***, EVEN POSTMESSAGE IS BLOCKING MY WORKER THREAD....

    What the heck am I doing wrong, all the documentation says these things run async, I can never get anything to run async between threads.
    Attached Files Attached Files

  9. #49
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,239

    Re: [ADVANCED] Multi-threaded VB6

    Quote Originally Posted by PsuFan View Post
    ***, EVEN POSTMESSAGE IS BLOCKING MY WORKER THREAD....

    What the heck am I doing wrong, ...
    You've only relabled a SendMessageA to PostMessage in your Declare:
    Declare Function PostMessage Lib "user32" Alias "SendMessageA"

    Also - in case you'll correct this later - take note that you should use PostMessage
    only in a low frequency from your Threads - because otherwise (e.g. when used as Progress-Callback in a high-frequented inner-loop),
    you'll risk MessageQueue-Flooding at the receiving end (the hWnd of the "other thread" which was perhaps busy for a second or two).

    I guess I'll never understand, why Timer-based Polling-approaches (as in the example I've posted),
    are always regarded that "unfavourably" in the community.

    Timerbased Polling is one of the few approaches, which allow you a true (and rock-stable)
    decoupling between "independent tasks" (when detecting "changed state" with nearly unmeasurable system-resource-usage).

    Olaf

  10. #50
    Frenzied Member
    Join Date
    Feb 2015
    Posts
    1,319

    Re: [ADVANCED] Multi-threaded VB6

    Quote Originally Posted by PsuFan View Post
    Looks promising, do you have the dim for WM_ID_ASYNCH_METHOD, cant find it anywhere...
    It's your own message like WM_USER + ...
    You can see how AsynchDispMethodCall works. Also there is InternetStatusCallback example where you can find the following methods:
    Code:
    Private Sub PutHandleAsync( _
                ByVal hwnd As Long, _
                ByVal hUrl As Long)
        PostMessage hwnd, WM_PUTHANDLE, hUrl, ByVal 0&
    End Sub
    
    Private Sub PutLogAsync( _
                ByVal hwnd As Long, _
                ByRef sText As String)
        PostMessage hwnd, WM_PUTLOG, SysAllocString(ByVal StrPtr(sText)), ByVal 0&
    End Sub
    
    Private Sub OnStatusCompleteAsynch( _
                ByVal hwnd As Long, _
                ByVal lStatus As Long, _
                ByVal lError As Long)
        PostMessage hwnd, WM_ONCOMPLETE, lStatus, ByVal lError
    End Sub
    
    ' // Window proc of async window in main thread
    Public Function AsyncWndProc( _
                    ByVal hwnd As Long, _
                    ByVal uMsg As Long, _
                    ByVal wParam As Long, _
                    ByVal lParam As Long) As Long
        Dim cObj    As CAsynchDownloader
        
        ' // Get object from window bytes
        vbaObjSetAddref cObj, ByVal GetWindowLong(hwnd, 0)
        
        Select Case uMsg
        Case WM_PUTLOG  ' // Show log entry
            Dim bstrText    As String
            
            ' // Extract string
            GetMem4 wParam, ByVal VarPtr(bstrText)
            
            cObj.PutLog bstrText
            
        Case WM_PUTHANDLE   ' // Put request handle
        
            cObj.RequestHandle = wParam
            
        Case WM_ONCOMPLETE  ' // INTERNET_STATUS_REQUEST_COMPLETE event
    
            cObj.OnStatusComplete wParam, lParam
            
        Case Else
            AsyncWndProc = DefWindowProc(hwnd, uMsg, wParam, lParam)
        End Select
        
    End Function

  11. #51
    Hyperactive Member
    Join Date
    Feb 2019
    Posts
    306

    Re: [ADVANCED] Multi-threaded VB6

    Quote Originally Posted by Schmidt View Post
    I guess I'll never understand, why Timer-based Polling-approaches (as in the example I've posted),
    are always regarded that "unfavourably" in the community.
    I have no objection against Timers, but PostMessage is almost instantaneous compared to Timers, and does the same job, but a Timer is easier to use, while PostMessage requires subclassing.

  12. #52
    Hyperactive Member
    Join Date
    Feb 2019
    Posts
    306

    Re: [ADVANCED] Multi-threaded VB6

    Quote Originally Posted by PsuFan View Post
    ***, EVEN POSTMESSAGE IS BLOCKING MY WORKER THREAD....

    What the heck am I doing wrong, all the documentation says these things run async, I can never get anything to run async between threads.
    Besides what others suggested, I don't see "Option Explicit" in any of the source files. Also, if you want a custom message, use one in the range of WM_APP, not WM_USER(VB Runtime and the Common Controls use some of WM_USER messages), or better yet, a custom message ID returned by RegisterWindowMessage.

  13. #53
    Frenzied Member
    Join Date
    Feb 2015
    Posts
    1,319

    Re: [ADVANCED] Multi-threaded VB6

    The timer message has the lowest priority than other messages.

    while PostMessage requires subclassing.
    Not necessary.

    Quote Originally Posted by qvb6 View Post
    Also, if you want a custom message, use one in the range of WM_APP, not WM_USER(VB Runtime and the Common Controls use some of WM_USER messages), or better yet, a custom message ID returned by RegisterWindowMessage.
    It isn't required for your own private windows.

  14. #54
    Frenzied Member wqweto's Avatar
    Join Date
    May 2011
    Posts
    1,365

    Re: [ADVANCED] Multi-threaded VB6

    In other words what The trick means is that you can post WM_KEYDOWN and receive Form_KeyDown event for instance -- no custom msg registration, no subclassing. There are other such pairs possible too.

    cheers,
    </wqw>

  15. #55
    Hyperactive Member
    Join Date
    Feb 2019
    Posts
    306

    Re: [ADVANCED] Multi-threaded VB6

    Quote Originally Posted by The trick View Post
    Not necessary.
    I know that one could post a message like WM_LBUTTONDOWN so simulate a click to a hidden control, so no subclassing is needed.
    Quote Originally Posted by The trick View Post
    It isn't required for your own private windows.
    Not sure what you mean, but for windows created from scratch, then WM_USER is okay to use, but anything else could use WM_USER messages, and worse, even if a control doesn't use WM_USER now, it could use one in future updates of the runtime, or Common Controls updates, while WM_APP is save to use in both cases.

  16. #56
    Frenzied Member
    Join Date
    Feb 2015
    Posts
    1,319

    Re: [ADVANCED] Multi-threaded VB6

    Quote Originally Posted by qvb6 View Post
    I know that one could post a message like WM_LBUTTONDOWN so simulate a click to a hidden control, so no subclassing is needed.
    Subclassing is a technique that allows an application to intercept and process messages sent or posted to a particular window before the window has a chance to process them. You can create your own message-only window and process the messages without subclassing. Alternatively, your thread can have no window at all but you can process the messages (PostThreadMessage).

    Quote Originally Posted by qvb6 View Post
    Not sure what you mean, but for windows created from scratch, then WM_USER is okay to use, but anything else could use WM_USER messages, and worse, even if a control doesn't use WM_USER now, it could use one in future updates of the runtime, or Common Controls updates, while WM_APP is save to use in both cases.
    Yes, i told about private window classes. Alternatively, you can use APC to call an arbitrary function in the context of the needed thread. The route thread can have only the loop with the SleepEx which switch the thread to the alertable state.

  17. #57

    Thread Starter
    Member
    Join Date
    Apr 2015
    Posts
    35

    Re: [ADVANCED] Multi-threaded VB6

    I appreciate everyone chiming in here, thanks guys.

    @ Schmidt, I did realize I forgot to change the alias. Nice catch, I didn't think it was going to fix anything. But it did, finally async notifications...

    I'm sure everyone will freak out about this statement but I like being event driven and it just seems cleaner to me. Plus I don't have to implement my own queue on top of a timer.

    I need it only rarely, when a user requests GUI change via web server.

    @ The trick, I looked for info on APC but couldn't find enough to implement.

    --------

    Using a hidden control may be even better. What are my options, are there any messages that don't take focus and allow me to send a int/long to identify the type of notification? I don't really want a fake form, prefer hidden control.

    How safe is passing pointers? Can you handle errors if the memory is moved via change by other thread?

    Edit: It doesn't look like WM_CHAR changes focus, may be able to use...
    PostMessage Text1.hWnd, WM_CHAR, Asc("A"), 0&
    Last edited by PsuFan; May 15th, 2019 at 08:46 PM.

  18. #58

    Thread Starter
    Member
    Join Date
    Apr 2015
    Posts
    35

    Re: [ADVANCED] Multi-threaded VB6

    Also for others trying, you cant use Schmidt's Form_Activate example with multiple forms, it executes multiple times. I couldn't get threading at startup, you will have to use one time timer to start threads if app has multiple forms (or store var to check if already loaded).

  19. #59
    New Member
    Join Date
    May 2018
    Posts
    11

    Re: [ADVANCED] Multi-threaded VB6

    For multithreading, the ThreadHandler in RC5c that I use is great overall, but there are still the following problems. For example, thread Dll debugging is difficult, and sometimes it crashes for no reason to find out exactly where it is.

    In addition, how to actively uninstall loaded threads? (th = regfree. ThreadObjectCreate (cThreadKey, ThreadLibPath, cThreadClass)) is set directly to set th = nothing?

    TH. JobQueueCount ‘represents the task currently executed (including the number of functions or processes being executed?)
    TH. CancelExecution ‘Is to cancel the task being performed? If multiple tasks are cancelled altogether?

    TH. TimeoutSecondsToHardTerminate 'What does this do?

  20. #60

    Thread Starter
    Member
    Join Date
    Apr 2015
    Posts
    35

    Re: [ADVANCED] Multi-threaded VB6

    I ended up using shared memory class / PostMessage(Form.hWnd, WM_CHAR, Asc("A"), 0&) / Private Sub Form_KeyPress(KeyAscii As Integer) for Async notifications. Seems to be pretty clean and doesn't have any issues. I cant even fake keypresses to the form via real user input. This specific app won't have a local user anyway.

    Thanks for all the help guys!

  21. #61
    Frenzied Member
    Join Date
    Jun 2012
    Posts
    1,230

    Re: [ADVANCED] Multi-threaded VB6

    Just for completeness.

    There is also an Ax-Dll http://www.vbforums.com/showthread.p...ultithreading) available to use multithreading in VB6. The workflow is similar to the BackgroundWorker in .net.

    Compared to an Ax-EXE it has two advantages:
    - The logic is in the app (and the code to be executued). So by any changes the app can be modified and the dll remains untouched as it's generic.
    - Can be used regfree via side-by-side manifest.

Page 2 of 2 FirstFirst 12

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width