0

I have a background thread like:

Public Class Main
   Private Sub StartBackgroundThread()
       Dim threadStart As New Threading.ThreadStart(AddressOf DoStuffThread)
       Dim thread As New Threading.Thread(threadStart)
       thread.IsBackground = True
       thread.Name = "Background DoStuff Thread"
       thread.Start()
   End Sub

   Private Sub DoStuffThread()
       Do
           Do things here .....
           If something happens Then
               ExitProgram(message)
           End If
       Loop
   End Sub

   Private Sub ExitProgram(ByVal message As String = "")
       MessageBox.Show(message)
       Application.Exit()
   End Sub

End Class

The thread keeps running to check some conditions, and once the condition is met, I want to call the ExitProgram to exit the whole application. The problem is the message box pops up without freezing the main thread (UI) resulting in the user can still operate on the UI which is not allowed.

I wonder how to call the ExitProgram method as it is called from Main thread so that the UI cannot be operated until the message box is dismissed ?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
dcc
  • 1,729
  • 4
  • 16
  • 17
  • What sort of application is this? Windows Forms? WPF? – Mick Sep 10 '14 at 03:51
  • possible duplicate of [Thread invoke the main window?](http://stackoverflow.com/questions/16424004/thread-invoke-the-main-window) – Mick Sep 10 '14 at 03:53

2 Answers2

1

Depending on the type of your application either...

C# Windows Forms Application - Updating GUI from another thread AND class?

or this...

Thread invoke the main window?

or this...

Using SynchronizationContext for sending events back to the UI for WinForms or WPF

Will answer your question i.e....

Public Class Main
   Dim _threadContext As SynchronizationContext

   Private Sub StartBackgroundThread()
       ' set on the UI Thread
       _threadContext = SynchronizationContext.Current;
       Dim threadStart As New Threading.ThreadStart(AddressOf DoStuffThread)
       Dim thread As New Threading.Thread(threadStart)
       thread.IsBackground = True
       thread.Name = "Background DoStuff Thread"
       thread.Start()
   End Sub

   Private Sub DoStuffThread()
       Do
           Do things here .....
           If something happens Then
               _message = message
               _threadContext.Post(o => { ExitProgram(message) }, null)
           End If
       Loop
   End Sub

   Private Sub ExitProgram(ByVal message As String = "")
       MessageBox.Show(message)
       Application.Exit()
   End Sub

End Class
Community
  • 1
  • 1
Mick
  • 6,527
  • 4
  • 52
  • 67
  • Hi, it is a WinForm application. I tried InvokeRequired or Invoke somethings, but the problem is the Main Class is not a control, which means it has no way to call Invoke method – dcc Sep 10 '14 at 05:03
  • The control or form you choose to do the invoke with need not have anything to do with the method. It's simply used to get the thread and synchronize the invoke. Are you saying you don't have a main form? – Mick Sep 10 '14 at 05:49
  • Hey Mick, what is the o => thing in VB? is that Linq? – dcc Sep 10 '14 at 06:45
  • The => is a lambda statement. http://stackoverflow.com/questions/3970219/c-sharp-lambda... Yes it is used in LINQ. I use C#, I haven't checked the validity of the syntax in vb i think it's right – Mick Sep 10 '14 at 06:51
  • it works. the VB version of the line is _threadContext.Post(AddressOf ExitProgram, message). Thanks a lot! – dcc Sep 10 '14 at 07:23
1

You can call the invoke method from your class. Do something like this

Create an Interface

Public Interface IContainerForm
    Function Invoke(ByVal method As System.Delegate) As Object
End Interface

Implement this Interface on your calling Form and pass its reference to the class

On the Form class do this

Public Class MyClass
    Implements IContainerForm

Private _obj As New MainClass(Me)

   Public Function Invoke1(ByVal method As System.Delegate) As Object Implements IContainerForm.Invoke
        Return Me.Invoke(method)
    End Function
End Class

Within your main class do this

 Dim _ContainerForm As IContainerForm

 Sub New(ByVal ContainerForm As IContainerForm)
        Me._ContainerForm = ContainerForm
    End Sub

To invoke now use

_ContainerForm.Invoke

In this way you can fulfill your requirement.

prem
  • 3,348
  • 1
  • 25
  • 57