Results 1 to 10 of 10

Thread: Simple Problem Using Invoke

  1. #1

    Thread Starter
    New Member
    Join Date
    Jun 2009
    Posts
    9

    Simple Problem Using Invoke

    I am working on adding multi-threading to my application. I have done two applications using multi-threading following a tutorial of sorts, and modifying the code to "get my feet wet."

    This is the first time I am trying multi-threading within my own application, and I feel I should be beyond this type of problem, but after a 3 hour search on the forums, I can not find a solution, so I am posting this thread.

    The section of code with the error
    vb.net Code:
    1. Imports System.Threading
    2. Imports SldWorks
    3. Imports SwConst
    4. Imports System
    5. Imports System.Windows.Forms
    6. Imports System.Globalization
    7. Imports System.Object
    8. Imports System.Math
    9.  
    10.     Public Parent As GCode
    11.  
    12.     Public Sub Initialize(ByVal oParent As Object)
    13.         'oGCode = oParent
    14.         Parent = oParent
    15.         .
    16.         .
    17.         .
    18.  
    19.         bResults = Parent.invoke(Parent.cSetTransform, swMathTransform)
    20.  
    21.     End Sub
    The error is:
    Error 1 'invoke' is not a member of 'ToyodaMill.GCode'.


    the Gcode class is as follows:
    vb.net Code:
    1. Imports System.Threading
    2. Imports SldWorks
    3. Imports System.IO
    4. Imports System.Text
    5.  
    6. Public Class GCode
    7.  
    8.     ReadOnly oTransformLock As New Object
    9.     Dim swTransform As MathTransform
    10.     Dim sTransformName As String
    11.  
    12.     Delegate Function dSetTransform(ByVal Transform As SldWorks.MathTransform)
    13.     Public cSetTransform As dSetTransform
    14.  
    15.  
    16.     Public Function SetTransform(ByVal Transform As SldWorks.MathTransform) As Boolean
    17.  
    18.         Monitor.Enter(oTransformLock)
    19.         SetTransform = True
    20.         Try
    21.             swTransform = Transform
    22.         Catch ex As Exception
    23.             SetTransform = False
    24.         Finally
    25.             Monitor.Exit(oTransformLock)
    26.         End Try
    27.     End Function
    Please help
    Last edited by Hack; Jun 15th, 2009 at 11:52 AM. Reason: Added Highlight Tags

  2. #2
    I'm about to be a PowerPoster! Hack's Avatar
    Join Date
    Aug 2001
    Location
    Searching for mendhak
    Posts
    58,333

    Re: Simple Problem Using Invoke

    Moved From The CodeBank

  3. #3
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    Re: Simple Problem Using Invoke

    Firstly, turn Option Explicit On (Make sure, option strict is also on).

    your parameter, oParent, is an Object. Your object 'parent' (not a good name, probably) is of type GCode. Gcode cannot be assigned from the parameter oParent. You want to cast (Cast, DirectCast or TryCast the passed parameter to the correct type).

    There is no Invoke method on your object GCode. Why not simply call your SetTransform method directly? It seems you may be overcomplicating things; there's no need (from what I can see) to do any invocation.
    "Ok, my response to that is pending a Google search" - Bucky Katt.
    "There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
    "Before you can 'think outside the box' you need to understand where the box is."

  4. #4

    Thread Starter
    New Member
    Join Date
    Jun 2009
    Posts
    9

    Re: Simple Problem Using Invoke

    option explicit is on,
    option strict is also on,

    I don't like the use of the word Parent either. My original code used oGCode instead. I switched because the test code which I was successful in multi-threading used the name Parent, and I thought it might be important. I will switch it back eventually.

    This code work fine when calling the function directly; However it is very calculation intensive. I therefore am trying to make the calculation part be on a separate thread from the UI. That way the dialog box will remain responsive while the program is running through its calculations.

  5. #5
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    Re: Simple Problem Using Invoke

    The only possible reason I see to be trying to invoke SetTransform is if Transform is a function that you need to have run on the UI thread. That would be the case if Transform alters the UI, but otherwise it seems unlikely.

    There is an alternative, which I have mentioned several times, but apparently I have never actually spelled it out, so I will do so here:

    I have used this concept in several places where I want a function run in a different thread (generally the UI thread, but it isn't necessary).

    1) Save the SynchronizationContext. Usually I am working in a class that runs a background thread. This context is common to a thread, not a class, so I always store it as a shared value:

    Private Shared uiContext As System.Threading.SynchronizationContext

    2) I then capture the UI context in the constructor using something like this:
    Code:
    If uiContext Is Nothing Then
                uiContext = System.Threading.SynchronizationContext.Current
            End If
    3) Having the synchronizationContext of the UI thread, it is now possible to post calls to subs that will be run in the UI thread, though there are some caveats as to what the sub looks like:
    Code:
    uiContext.Post(AddressOf <my sub>,state as Object)
    Note that Post will be an asynchronous call, while Send would be synchronous. The sub has to take a single argument of type Object, which is the state argument of the Post call. This can be awkward, but heck, an Object can be ANYTHING, so just put what you need in it. If you need to call a sub that has multiple arguments, make a dummy sub that takes all the arguments as members of a class, then have that dummy sub unpack the arguments from the class and call the proper sub with the arguments. The key is that the sub called by the Post will be called in the UI context.
    My usual boring signature: Nothing

  6. #6
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    Re: Simple Problem Using Invoke

    Oops, I had two conversations between starting that post and posting it, so I missed your reply. The bulk of it might still help, though.
    My usual boring signature: Nothing

  7. #7
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    Re: Simple Problem Using Invoke

    Option Strict is ON? With this code?

    Public Parent As GCode

    Public Sub Initialize(ByVal oParent As Object)
    Parent = oParent

    ...


    I'm sorry, but I can't believe that. You should have an error on the Parent = oParent line.

    If you want the calculation to run in a different thread then why not create a thread for it to run on? Although Shaggy has a good point (The synchronizationContext is a good tool), unfortunately you haven't shown anywhere that a thread is being created.

    There are various methods of encapsulation, but it's very application specific. But creating a thread is extremely simple. What you may want to do is encapsulate the thread within a class, with a 'calculate' method which actually creates a thread and raises an event when complete.

    Code:
    	Private Class Calculator
    
    		Public Event WorkComplete()
    
    		Public Sub Calculate()
    			Dim t As New System.Threading.Thread(AddressOf CalculateThread)
    			t.IsBackground = True
    			t.Start()
    		End Sub
    
    		Private Sub CalculateThread()
    			' Do The Work
    			RaiseEvent WorkComplete()
    		End Sub
    
    	End Class
    If you want to pass an object to the thread, then you'd use a parameterized Thread:

    Code:
    	Private Class Worker
    
    	End Class
    
    	Private Class Calculator
    
    		Public Event WorkComplete()
    
    		Public Sub Calculate(ByVal workParameters As Worker)
    			Dim t As New System.Threading.Thread(New Threading.ParameterizedThreadStart(AddressOf CalculateThread))
    			t.IsBackground = True
    			t.Start()
    		End Sub
    
    		Private Sub CalculateThread(ByVal obj As Object)
    			Dim w As Worker = TryCast(obj, Worker)
    			If w Is Nothing Then
    				' Do something with a bad worker object
    			End If
    			' Do The Work
    			RaiseEvent WorkComplete()
    		End Sub
    
    	End Class
    "Ok, my response to that is pending a Google search" - Bucky Katt.
    "There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
    "Before you can 'think outside the box' you need to understand where the box is."

  8. #8

    Thread Starter
    New Member
    Join Date
    Jun 2009
    Posts
    9

    Re: Simple Problem Using Invoke

    In this case swTransform is a piece of data, (it is a SolidWorks Math Transform Object which contains the zero point with respect to the actual origin, as well as the rotational, translational, and scaling data.)

    SetTransform and GetTransform are functions to get and set the variable swTransform. This data is on the UI thread, and is used in both the UI (locating the origin) and the calculation thread.

    I asked in another post about storing the data on a separate thread other than the UI and calculation thread, but from the comments, I do not believe it would be of any benefit, so I put the data on the UI thread.

    I am not certian about the synchronization, but I will give it a try.

  9. #9
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    Re: Simple Problem Using Invoke

    The data is not on any thread. Data is not tied to a thread, which is why you have that Monitor in there. Any thread can access any data that is within scope, so multiple threads could alter or access the same data item at any time, thereby causing race conditions...potentially. Don't be thinking about a thread as owning data (other than local variables tied to a single routine), or you will cause yourself trouble down the road.

    SynchronizationContexts are both useful, simple, and poorly documented. If a thread calls a sub, the sub will run in the thread that called it. To have a thread cause a sub to run in a different context, the SynchronizationContext is really nice. I was actually using this technique to call a sub that would raise events. If the thread called the sub directly, the event would be raised on the background thread, which is not what I wanted.
    My usual boring signature: Nothing

  10. #10
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    Re: Simple Problem Using Invoke

    Something else to think about: you don't 'store' data on a thread - threads are simpler than that. Any data accessible from one thread, is available to another thread (depending on scope).

    You have used a Monitor, so you obviously have something in mind to ensure synchronicity. If you hold your (transform) data within the object which creates your thread it's probably going to be easier to synchronize those objects with the UI and the calculation.
    "Ok, my response to that is pending a Google search" - Bucky Katt.
    "There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
    "Before you can 'think outside the box' you need to understand where the box is."

Posting Permissions

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



Click Here to Expand Forum to Full Width