dcc
dcc

Reputation: 1739

How to freeze the main thread from a worker thread

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 ?

Upvotes: 0

Views: 524

Answers (2)

Mick
Mick

Reputation: 6864

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

Upvotes: 1

prem
prem

Reputation: 3538

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.

Upvotes: 1

Related Questions