Hi,

Even though there are many examples of Invoke operations, I can't find something that works for me. (I'm using VS 2008, and working in VB)

Here is what i have:

A main module with functions (thread 1) that starts a BeginRead for a TCPClient. When the callback function executes (on thread 3), I want to call a function from the main module, in the main thread. All I get even with Invokes is calling functions that always run in thread 3, not the parent thread.

I call:

MsgBox("Function name: " & Thread.CurrentThread.ManagedThreadId)

in each of my functions do determine on what thread it is executed. At some point, from the infinite read callback function I will have to get a function to show a form, but that function gets caught in the callback thread and freezes, instead of running in the main thread.

Any suggestions ?

Thanks

PS: the callback that I pass to the BeginRead of the TCPClient is a function, not a class, so I can't use raise events.

All I need is to call a function to run in the main thread (main module) from another thread.

Recommended Answers

All 8 Replies

try this:

create a global delegate

Private Delegate Sub ShowDelegate

Then a function

private sub ShowFrm
myForm.show
end sub

all you have now to do is to replace your crossthread line with

Me.invoke(new ShowDelegate(Addressof Showfrm))

Hi,

Thank you for your reply.

I know your solution works, but Me. is only available when written inside a form, as it refers to the form.

I am only in a function of a separate thread, wanting to call another sub on the main thread, and I cannot use Me. if I am not in a form.

I assume your "main thread" is UI thread i.e. the function you're trying to call is inside a form class.

The code in the UI thread should be similar to this:

Private Delegate Sub DelegateForSomeSub(ByVal arg0 As Integer, ByVal arg1 As Integer)

Public Sub SomeSub(ByVal arg0 As Integer, ByVal arg1 As Integer)
    If Me.InvokeRequired Then
        ' Argument array for the delegate
        Dim args As Object() = {arg0, arg1}
        ' Method to call
        Dim SomeSubDelegate As DelegateForSomeSub
        SomeSubDelegate = AddressOf SomeSub
        ' After this you're in the main thread (UI thread)
        Me.Invoke(SomeSubDelegate, args)
        Exit Sub
    End If

    ' Actual procedure code is in here

End Sub

Now you should be able to invoke SomeSub from the currently running separate thread by calling <classname>.SomeSub(1,2). For example if the main thread (UI thread) is in Form1 class, you call Form1.SomeSub(1,2) from the other thread.

If you call SomeSub inside the main thread, Me.InvokeRequired returns False and the procedures actual code is executed straight away.

HTH

No :), the "main thread" is just a module, not a form. There is no UI yet. The function I am trying to call in in a module. No forms are created yet.

Ok, I tried to re-create a similar situation and the result was not very encouraging.

What you want can be done (I'm sure), but I suggest an easier approach.

Add to your project (solution) a new windows forms project. Set it as a startup project. Once you run the application and the main form's initialization is done, set the form hidden and call your original main procedure. This way you a) have a ready UI thread when you need it later and b) the UI thread stays "alive".

WinForm application (i.e. your UI) could also be a separately running application. There's only some issues weather your main parts of the code is in-process (dll) or out-of-process (exe) component.

I'm not 100% sure (didn't had time to examine this) why showing the form wasn't as easy as I thought it would be. The reason could be that when you create a new, empty WinForm project from a template, there's already a whole lot of code "behind the scenes".

Thanks you for testing this case, yes I know it works this way, and I have already done this many times. Just trying to make it "cleaner" without hidden forms this time.

Thank you very much Teme64 for your effort. I solved the problem. This is a sample:

Imports System.Threading
Module Module1

    Private SC As New WindowsFormsSynchronizationContext

    Public Sub Main()
        Dim T As New System.Threading.Thread(AddressOf Threaded)
        T.IsBackground = True
        T.Start()

        While True
            Thread.Sleep(1000)
            Debug.Print("Main: " & Thread.CurrentThread.ManagedThreadId)
            Application.DoEvents() ' <-- otherwise the "Posted" SynchronizedCallBack() calls won't get executed
        End While
    End Sub

    Private Sub SynchronizedCallBack()
        Debug.Print("SynchronizedCallBack: " & Thread.CurrentThread.ManagedThreadId)
    End Sub

    Private Sub Threaded()
        While True
            Thread.Sleep(5000)
            Debug.Print("Threaded: " & Thread.CurrentThread.ManagedThreadId)
            SC.Post(New SendOrPostCallback(AddressOf SynchronizedCallBack), Nothing)
        End While
    End Sub

End Module

And I also have another post, if you would like to take a look, I'd be grateful if you did:
http://www.daniweb.com/forums/thread293989.html

Thanks a lot.

Hi! Nice to hear that you got answer to your problem. Could you please mark the thread as solved. Thank you! I'll take a look at the other thread too...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.