true multithreading in vfp

in this 4th part i will describe here a way of obtaining true multi threading with vfp and the interop toolkit usercontrol. as you know this is impossible in vfp alone although there are some ways of achieving this through com and use of timers.

the method for doing this has been adapted from the code found here:
http://www.codeproject.com/kb/vb-interop/vb6interoptoolkit2.aspx
you should also read this article thoroughly.

so fire up vb 2005 express and create a new interop user control project..see here for how.  name it multithreadedcontrol. rename the interopusercontrol.vb to bbinteropusercontrol.vb

open the control in design mode and add the following 3 objects to the user control:

label   -> change the name property to labelmessage
progressbar
backgroundwoker  (found under components)

arrange them so the control looks like this:
<!--[if !supportlinebreaknewline]-->
<!--[endif]-->


now double click the control to open the code window, and type in the following code as shown or copy and paste the code in green below.

'please enter any new code here, below the interop code
    public event startevent(byval starteventtext as string)
    public event finishasyncevent(byval endeventtext as string)
    public sub startprocessing()
        try
            ' commented out see explanation later on
            'raiseevent startevent("starting .net process ...")
            me.backgroundworker1.runworkerasync()
        catch
        end try
    end sub
    private sub backgroundworker1_dowork(byval sender as system.object, _
    byval e as system.componentmodel.doworkeventargs) _
    handles backgroundworker1.dowork
        'wait for a while
        static prog as integer = 0
        ' moved from sub above. see explanation below.

        raiseevent startevent("starting .net process ...")

        while (prog < 100)
            system.threading.thread.sleep(250)
            prog = prog + 2
            me.backgroundworker1.reportprogress(prog)
        end while
        prog = 0
    end sub
    private sub backgroundworker1_progresschanged(byval sender as system.object, _
    byval e as system.componentmodel.progresschangedeventargs) _
    handles backgroundworker1.progresschanged
        me.labelmessage.forecolor = color.red
        me.labelmessage.text = "working in background..."
        me.labelmessage.visible = true
        me.progressbar1.value = e.progresspercentage
    end sub
    private sub backgroundworker1_runworkercompleted(byval sender as system.object, _
    byval e as system.componentmodel.runworkercompletedeventargs) _
    handles backgroundworker1.runworkercompleted
        me.labelmessage.visible = false
        raiseevent finishasyncevent("background interop user control process finished.")
    end sub
    private sub backgroundworker_load(byval sender as system.object, _
    byval e as system.eventargs) handles mybase.load
        me.progressbar1.value = 0
        me.labelmessage.visible = false
    end sub
end class

<!--[if !supportlinebreaknewline]-->
correct any errors in your typing.

make sure the backgroundworker has had the appropriate events set:


also make sure that you turn on progress checking as shown below:
<!--[if !supportlinebreaknewline]-->
<!--[endif]-->



that's it for the net part. now build your solution and an activexdll will be created called multithreadedcontrol.dll and will appear as an activex in vfp.

switch over to vfp now and create a new form. add objects and set their properties as shown:

<!--[if !supportlinebreaknewline]--><!--[endif]-->

edit2 is an editbox that is made readonly and the disabled baclcolor set to yellow.
our usercontrol is added at the bottom in the usual way an activex is added.

now lets get on with the vfp side code.

in the button.click event add code as shown to first clear the editbox out, then display a message and finally to kick off the background process. as you type you can see intellisense takes over and displays the sub we exposed in .net

public sub startprocessing()
<!--[if !supportlinebreaknewline]--><!--[endif]-->


now you need to hook in the 2 events we exposed:

public event startevent(byval starteventtext as string)
public event finishasyncevent(byval endeventtext as string)

so doubleclick on the interop control and select the startevent from the list. you can see that vfp adds the appropriate parameter statement. add code as shown to broadcast the start event.
<!--[if !supportlinebreaknewline]-->
<!--[endif]-->
funnily enough i was unable to get this event to fire although the code to start the process does work.

later on - correction
it appears that you cannot raise an event within an exposed method in a .net com if you call that method directly. you can only raise the event if the trigger is within .net.

in the code above :
public sub startprocessing()
    try
       raiseevent startevent("starting .net process ...")
       me.backgroundworker1.runworkerasync()
    catch
    end try
end sub

i am calling the exposed sub startprocessing from my button and this in turn is raising the startevent. this does not work in vfp and .net.

so move the event into the method that actually does the work. that is triggered within .net and you can raise the event there.

raiseevent startevent("starting .net process ...")
 
while (prog < 100)
     system.threading.thread.sleep(250)
     prog = prog + 2
     me.backgroundworker1.reportprogress(prog)
end while


why this happens is anyone's guess but happen it does. go figure.




also add code to handle the finishasyncevent as shown:
<!--[if !supportlinebreaknewline]-->
before we finish, make sure the form has these properties set:
<!--[if !supportlinebreaknewline]-->
<!--[if !vml]--><!--[endif]-->

your form is ready to run. so just go ahead and run the form. type something in the topmost editbox. then click the process button to kick off the background process in another thread.
<!--[if !supportlinebreaknewline]--><!--[endif]-->



you will find that you can continue typing in the editbox and do other things, while the process runs. feedback on its progress can be seen by the progress bar. once the process has completed, you are notified by the finishasyncevent firing. this causes our final piece of code to run and displays the message in the yellow editbox.
<!--[if !supportlinebreaknewline]--><!--[endif]-->



and there you have it. true multithreading in vfp with .net. but why stop there. how about adding another multithreading component. below is an image of a form - multi2.scx, running 2 processes while allowing you to type and do other processes.

in the next article i hope to show how you can spawn multiple processes in separate threads using com and a .net multithreadfactory object.

the complete source code for the above can be downloaded from the attachment link below:

unfortunately because of the amount of junk mail being generated from the weblog i have switched off comments. please post your comments, if any, at www.foxite.com

8 Responses to Using the Interop Forms Toolkit in VFP9 – IV

  • Luis Navas says:

    Good one Bernard, thank you for sharing it

  • Cesar says:

    Hi Bernard,

    Thanks a lot for introducing the Interop Forms.
    You’re opening some really interesting doors.

    For the purpose of Multithreading, have you already looked at Claude Fox’s project ?

    http://www.codeplex.com/mtmyvfp

    Regards

    Cesar

    Hi Cesar

    I have. It uses a VFP MT DLL. As I mentioned in my post, it is somewhat possible using a COM server.

    This method is true multi threading since the whole process runs in a separate thread and there are callbacks also to show progress. Besides it will expose some of the VFP community to .NET which is not such a bad thing.
    Bernard

  • John Reviews says:

    Cool!

  • Tarik Alkathiri says:

    Thank you very much for the great tool,

    And thanks a lot for sharing it.

    Please keep the good things going.

    Best Regards

    Tarik

  • edyshor says:

    Ok, now how do you make this a multipupose multithreading object in vfp? I mean, create the object, then feed it vfp code (or instruction to run a vfp function or method from current app will be best) and instruct it to run in in a new thread (with hooks of course: progress, finished, started, eventchatcher – events fired from the running code in that specific thread) ?!

    I know that you’ve just gave us a glimpse and shown us that its posible, but it doesn’t realy help if the code to run in different thread has to be .net 🙁

    You already have the answer in your question except you dont see it. What you do is create a passthru function in the .Net component. .Net cannot run commands like VFP does (as a macro using &Command2Run) so you need VFP to do that. Just create a simple passthrough VFP COM DLL and refrence it in .NET. The exposed methd in .NET will accept one parameter – a string. It will then pass this string to the VFP DLL and the VFP DLL will execute the code using & macro. It may sound complicated but is actually something that will take about 15 minutes to implement.

    In fact I alluded to this in my post about creating a Factory object to do the heavy lifting. Think about it and if you are still stuck, drop me another line here or on Foxite and I will show you how.

  • edyshor says:

    I see what you mean, something like Calvin Hisia’s favorite COM dll 🙂
    But in any case, say i have an app object with some methods, each of those methods does things that should be done more or less simultaneous and the code in the methods takes a while to complete (so having them run one after another is not an option, even from a timer). The code relies on properties, variables, application states, etc.
    In short, i’m asking how can make an application execute code (“in-application”) but simultaneous (“multithreaded”).
    Or, if this isn’t possibly in vfp, what kind of communication mechanism i can setup so the code in threads can communicate with the running app requesting/sending data (as in information, not cursors or records).
    Then there’s the problem with the application having to shutdown it’s threads before shutting down herself.
    I don’t want you to think that i’m asking you to do my homework or something, but i have lots of questions on getting multithreading in my vfp applications and very few answers 🙁

    You don’t appear to have a complete understanding about threads. They may be instantiated from the same process but execute isolated. The only interaction you should have with a thread is through callbacks or else you do not have an isolated thread with problems of memory seepage and other things.

    Unfortunately with just the bare outline you have given you will not find answers here or elsewhere. This is not a forum so posting answers is not an option.

    With that in mind, I suggest you start a thread on Foxite http://www.foxite.com so that I can help you better. You are a member there aren’t you? Its free, and there are a large number of experts willing to help. So drop by, post a detailed question and then I will take it from there.

  • edyshor says:

    I just got an idea, is it feasible to access my running application from the threaded code with GetObject(“MyApp.Applications”) to get/set running application’s properties and executing methods (triggering events) ?

    It may be feasible but not recommended. Please post all queries on http://www.foxite.com.

  • edyshor says:

    Ok, Bernard, i’ve started a thread on Foxite at http://www.foxite.com/archives/vfp-multithreading-with-callbacks-0000178394.htm

    I’m posting the link here so that if anyone else will google around for vfp and multithreading and find this post as i did, they’ll find the thread with ease, i hope you don’t mind.

    Good idea.

Leave a Reply

Your email address will not be published. Required fields are marked *