Question

I have some method run in the UI thread. Inside this method a new thread is created. I need UI thread waits until this new thread is finished because I want to wait for some results to be able to continue the method. But I don´t want to have UI frozen so meanwhile UI thread is waiting, it is also responding with UI.

Here is what I have now:

Dim _WaitHandler As New System.Threading.AutoResetEvent(False)

Public Sub Method()

   For i As Integer = 0 To 100

      Dim myThread As Thread = New Thread(AddressOf ThreadMethod)
      myThread.Start()

      _WaitHandler.WaitOne()

      //next loop or exit?
   Next

   //this code I want to process after myThread is finished
   //but also I don´t want to freeze UI during WaitOne method

End Sub

Private Sub ThreadMethod()

   //do something...
   _WaitHandler.Set()

End Sub

It seems that during WaitOne method UI thread sleeps and it doesn´t response so UI is frozen. Have you any idea where is the problem? Thank you guys.

EDIT Here is a thing a forgot to write you: myThread creating is inside a for cycle. After myThread is finished, based on a results from myThread I have to decide If I should continue in the cycle (next loop) or exit cycle. My code is edited.

If I use a BackgroundWorker, UI thread will automatically continue with next loop.

Was it helpful?

Solution

UI thread should not wait anything. It's a bad practice. Use Background Worker and attach apropriate listeners to events DoWork, ProgressChanged, RunWorkerCompleted http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx

OTHER TIPS

If you use ThredSleep, or WaitOne. It will obviously freeze the screen because the main UI thread is stopped/waiting. I recommend you use Tasks and set a CallBack so the background job runs without freezing the UI. So can get the task result in a callback.

I give you an example:

 new TaskFactory().StartNew(BackGroundTask).ContinueWith(TaskCancelationCallBack);  

//get the result in a callback

private void TaskCancelationCallBack(System.Threading.Tasks.Task task)
{

     //Get Task Result
} 

The UI is nearly always waiting, anyway - waiting for user input and other data. It's a state-machine, fed with messages via. an input queue. You should treat it as such, and provide thread-completion information as just another input message.

You should not try to expicitly wait in a GUI event-handler, no matter how tempting it may seem initially.

Look at Control.BeginInvoke() or Task class.

This pattern should do what you want

Public Sub Method()
    Dim myThread As Threading.Thread = New Threading.Thread(AddressOf ThreadMethod)
    myThread.IsBackground = True
    myThread.Start()
End Sub

Private Sub ThreadMethod()
    'do something...
    AfterThreadMethod()
End Sub

Delegate Sub AfterThreadMethodDel()
Private Sub AfterThreadMethod()
    '   //this code I want to process after myThread is finished
    'if this code must run on the UI then
    If Me.InvokeRequired Then
        'not on the UI
        Dim foo As New AfterThreadMethodDel(AddressOf AfterThreadMethod)
        Me.Invoke(foo)
    Else
        'on the UI
    End If
End Sub
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top