none
VB.Net System.Threading.Thread.Sleep(X) Application (Not Responding) RRS feed

  • Question

  • I have this little application that is using a System.Threading.Thread.Sleep, application runs great but Windows thinks the application is not responding even though it is running.  suggestions on a better or cleaner method, I'm teaching myself so need a little help.  thanks in advance.   

    Imports System.Threading Public Class FormMain Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Try If CheckBoxRepeat.Checked = True Then LabelRepeat.ForeColor = Color.Red Dim var As Integer Dim startVal As Integer Dim endVal As Integer startVal = 1 endVal = (10) For var = startVal To endVal LabelRepeat.Text = (10 & " Times, " & " Sent " & var + 1 & " Times," & " Delay " & 10 & " Seconds.") LabelRepeat.Refresh() System.Threading.Thread.Sleep(10000) Next var

    MsgBox("Done!") End If Catch ex As Exception MsgBox(ex.ToString) End Try End Sub End Class


    Sunday, May 13, 2012 10:29 PM

Answers

  • Thank you,  I found this: http://www.youtube.com/watch?v=jv4FdoaUMQE

    but my above code worked but I needed to add

     Private Sub FormMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Control.CheckForIllegalCrossThreadCalls = False
    
        End Sub

    Thoughts?  Full code snippet:

    Imports System.Threading
    
    Public Class FormMain
    
        Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, _
          ByVal e As System.ComponentModel.DoWorkEventArgs) _
          Handles BackgroundWorker1.DoWork
    
            Try
                If CheckBoxRepeat.Checked = True Then
                    LabelRepeat.ForeColor = Color.Red
                    Dim var As Integer
                    Dim startVal As Integer
                    Dim endVal As Integer
                    startVal = 1
                    endVal = (5 - 1)
    
                    For var = startVal To endVal
                        LabelRepeat.Text = (5 & " Times, " & "  Sent " & var + 1 & " Times," & "  Delay " & 10 & " Seconds.")
                        LabelRepeat.Refresh()
                        System.Threading.Thread.Sleep(10000)
                    Next var
    
                End If
                MsgBox("Done!")
            Catch ex As Exception
                MsgBox(ex.ToString)
            End Try
    
        End Sub
    
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            ' Start up the BackgroundWorker1.
            BackgroundWorker1.RunWorkerAsync()
        End Sub
    
        Private Sub FormMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Control.CheckForIllegalCrossThreadCalls = False
    
        End Sub
    End Class
    

     
    • Marked as answer by jimbrown.ws Monday, May 14, 2012 1:36 AM
    Monday, May 14, 2012 12:10 AM
  • Try this. I am curious as to why you created an app that just loops and sleeps ?

    Imports System.Threading
    
    Public Class Form1
        Dim DelayHowlong As Integer = 1
        Dim HowManyLoops As Integer = 10
    
        Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, _
          ByVal e As System.ComponentModel.DoWorkEventArgs) _
          Handles BackgroundWorker1.DoWork
            Try
                If CheckBoxRepeat.Checked = True Then
                    LabelRepeat.ForeColor = Color.Red
                    Dim var As Integer
                    For var = 1 To HowManyLoops
                        System.Threading.Thread.Sleep(DelayHowlong * 1000)
                        BackgroundWorker1.ReportProgress(var)
                    Next var
    
                End If
            Catch ex As Exception
                MsgBox(ex.ToString)
            End Try
    
        End Sub
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            BackgroundWorker1.WorkerReportsProgress = True
            BackgroundWorker1.RunWorkerAsync()
        End Sub
    
        Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
            Dim var As Integer = e.ProgressPercentage
            LabelRepeat.Text = (HowManyLoops.ToString & " Times, " & "  Sent " & var.ToString & " Time(s)," & " Delay = " & DelayHowlong.ToString & " Second(s).")
            LabelRepeat.Refresh()
        End Sub
    
        Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
            MsgBox("Done!")
        End Sub
    End Class

    • Marked as answer by jimbrown.ws Monday, May 14, 2012 2:11 PM
    Monday, May 14, 2012 2:36 AM
  • Control.CheckForIllegalCrossThreadCalls = False
    This is a bad practice.

    If you want something you've never had, you need to do something you've never done. If you believe something to be true, then one day you will be called upon to demonstrate that truth.

    Thursday, August 9, 2012 9:55 PM
    Moderator

All replies

  • Jim,

    You're doing that in the main UI thread, that's why. With little exception, don't put a "sleep" in the main UI thread (and for that matter, try avoid using it at all).

    Look into using a BackgroundWorker to run that on another thread but, as you have it, it won't work -- you can't "touch" any controls on the main UI thread, but you can use the events to update those those controls on the main UI thread.


    Please call me Frank :)

    Sunday, May 13, 2012 10:33 PM
  • When you put your application to sleep (on the UI thread as you have done) it doesn't  respond when Windows checks it state.  It's not running  when it's sleeping.  If it were, it would be "sleep running" which is even more dangerous than "sleep walking".
    Sunday, May 13, 2012 10:39 PM
  • What did I miss?

    Imports System.Threading
    
    Public Class FormMain
    
        Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, _
          ByVal e As System.ComponentModel.DoWorkEventArgs) _
          Handles BackgroundWorker1.DoWork
    
            Try
                If CheckBoxRepeat.Checked = True Then
                    LabelRepeat.ForeColor = Color.Red
                    Dim var As Integer
                    Dim startVal As Integer
                    Dim endVal As Integer
                    startVal = 1
                    endVal = (10)
    
                    For var = startVal To endVal
                        LabelRepeat.Text = (10 & " Times, " & "  Sent " & var + 1 & " Times," & "  Delay " & 10 & " Seconds.")
                        LabelRepeat.Refresh()
                        System.Threading.Thread.Sleep(10000)
                    Next var
    
                End If
                MsgBox("Done!")
            Catch ex As Exception
                MsgBox(ex.ToString)
            End Try
    
        End Sub
    
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            ' Start up the BackgroundWorker1.
            BackgroundWorker1.RunWorkerAsync()
        End Sub
    
    End Class
    

    Sunday, May 13, 2012 11:02 PM
  • What did I miss?

    You cannot, in any way, touch any control on the main UI thread -- nothing.

    Pass in the information as a parameter or give it another way to get the information, and pass out the information that you want show back on the UI thread, but you cannot [directly] get anything from any control on the main UI.


    Please call me Frank :)

    Sunday, May 13, 2012 11:06 PM
  • Sorry Frank,  I need an example.  I am teaching my self VB.Net.  I will try and find a BackgroundWorker example that is not overly complicated.  thanks for your help so far.  
    Sunday, May 13, 2012 11:15 PM
  • Sorry Frank,  I need an example.  I am teaching my self VB.Net.  I will try and find a BackgroundWorker example that is not overly complicated.  thanks for your help so far.  

    I understand, and don't mind providing it, but it seems our timing is once again out of whack!

    John Wein is a quintessential expert on threading (heck, pretty much anything else too!) and if he or someone else doesn't come up with an example that you can use, then sometime tomorrow I will for you. Of course, tomorrow is Monday so it's "back to regular work" but I'll do what I can when I can.

    A BGW isn't hard to work with, but at first it can be confusing. Start with the minimum then work forward and you'll see it's really not all *that* big of a deal. The one cardinal rule though, never even look at the main UI controls for anything -- not even a count of something!

    In time you'll get it and I have to admit that the online help is anything but helpful (or it wasn't to me), so I fully understand your frustration.


    Please call me Frank :)

    Sunday, May 13, 2012 11:25 PM
  • Thank you,  I found this: http://www.youtube.com/watch?v=jv4FdoaUMQE

    but my above code worked but I needed to add

     Private Sub FormMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Control.CheckForIllegalCrossThreadCalls = False
    
        End Sub

    Thoughts?  Full code snippet:

    Imports System.Threading
    
    Public Class FormMain
    
        Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, _
          ByVal e As System.ComponentModel.DoWorkEventArgs) _
          Handles BackgroundWorker1.DoWork
    
            Try
                If CheckBoxRepeat.Checked = True Then
                    LabelRepeat.ForeColor = Color.Red
                    Dim var As Integer
                    Dim startVal As Integer
                    Dim endVal As Integer
                    startVal = 1
                    endVal = (5 - 1)
    
                    For var = startVal To endVal
                        LabelRepeat.Text = (5 & " Times, " & "  Sent " & var + 1 & " Times," & "  Delay " & 10 & " Seconds.")
                        LabelRepeat.Refresh()
                        System.Threading.Thread.Sleep(10000)
                    Next var
    
                End If
                MsgBox("Done!")
            Catch ex As Exception
                MsgBox(ex.ToString)
            End Try
    
        End Sub
    
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            ' Start up the BackgroundWorker1.
            BackgroundWorker1.RunWorkerAsync()
        End Sub
    
        Private Sub FormMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Control.CheckForIllegalCrossThreadCalls = False
    
        End Sub
    End Class
    

     
    • Marked as answer by jimbrown.ws Monday, May 14, 2012 1:36 AM
    Monday, May 14, 2012 12:10 AM
  • A better method I think would be to set the WorkerReportsProgress of the backGroundWorker to True

    inside your loop call the ReportProgress, passing the value of the for-next variable

    add a sub for BackGroundWorker.Progress changed, and move the label update code to there.

    Monday, May 14, 2012 12:37 AM
  • Thanks,  is it bad the way I have it?  I tried WorkerReportProgress =  True and the below code but my var is not part of this sub and did not update my labelRepeat.Text.  please give me a example. 

     Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
            LabelRepeat.Text = (My.Settings.Repeat & " Times, " & "  Sent " & var + 1 & " Times," & "  Delay " & My.Settings.Delay & " Seconds.")
            LabelRepeat.Refresh()
        End Sub

    Monday, May 14, 2012 1:33 AM
  • Try this. I am curious as to why you created an app that just loops and sleeps ?

    Imports System.Threading
    
    Public Class Form1
        Dim DelayHowlong As Integer = 1
        Dim HowManyLoops As Integer = 10
    
        Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, _
          ByVal e As System.ComponentModel.DoWorkEventArgs) _
          Handles BackgroundWorker1.DoWork
            Try
                If CheckBoxRepeat.Checked = True Then
                    LabelRepeat.ForeColor = Color.Red
                    Dim var As Integer
                    For var = 1 To HowManyLoops
                        System.Threading.Thread.Sleep(DelayHowlong * 1000)
                        BackgroundWorker1.ReportProgress(var)
                    Next var
    
                End If
            Catch ex As Exception
                MsgBox(ex.ToString)
            End Try
    
        End Sub
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            BackgroundWorker1.WorkerReportsProgress = True
            BackgroundWorker1.RunWorkerAsync()
        End Sub
    
        Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
            Dim var As Integer = e.ProgressPercentage
            LabelRepeat.Text = (HowManyLoops.ToString & " Times, " & "  Sent " & var.ToString & " Time(s)," & " Delay = " & DelayHowlong.ToString & " Second(s).")
            LabelRepeat.Refresh()
        End Sub
    
        Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
            MsgBox("Done!")
        End Sub
    End Class

    • Marked as answer by jimbrown.ws Monday, May 14, 2012 2:11 PM
    Monday, May 14, 2012 2:36 AM
  • Glad to see that you got it worked out then. :)

    Please call me Frank :)

    Monday, May 14, 2012 12:34 PM
  • Glad to see that you got it worked out then. :)

    Please call me Frank :)


    He didn't.  He found a way to ignore the problem.
    Monday, May 14, 2012 12:56 PM
  • Monday, May 14, 2012 2:11 PM
  • Even though this has been answered now (twice over), I'm going add my version of how I'd use a BackgroundWorker in a program. In my example, it does something which is fairly common to do in a BGW: Copy files and report the progress along the way.

    In it, you'll see some practices which some shun here (and I still think are perfectly fine), but use your own discretion with it. I also show a way to pass information into the BGW as an object, how to then "extract" it back out and use it, how to handle an exception being thrown, how to cancel it midstream, and even the use of a delegate so that we can use a function which is outside the reach of the BGW.

    I have the code on a web page of my site and you can view it by clicking here.

    The program's UI is set up like this:

    Once they select the source and target folders to copy from/to, the "Start File Copy" button is enabled:

    The user is first asked to confirm that they want to proceed:

    ... and it then proceeds as instructed:

    There are three possible outcomes. The first being a successful completion:

    ...the second being if they choose to cancel it:

    ... and the last being if an exception was raised during the BGW's run:

    If they try to close the program while it's running, they'll see this:

    So for what it's worth -- I thought I'd add this to the thread. :)

    Please call me Frank :)


    Monday, May 14, 2012 10:51 PM
  • Frank, great example for using BGW - it has helped me a lot.

    Question, I would like to count the subfolders as they are copied to the destination. Once the process has finished copying I would like to show how many files\ folders were copied and how long it took. I know it's inane but It makes me happy :O)

    I have managed to get a file count and time elapsed but struggling with identifying the folders as they are being copied. I think it is a case of not seeing the wood for the trees.

    I have cheated by calling a sub at the end of your program to recursively ‘get the directories’ of the newly copied destination folder. This does work but I feel it is clumsy and a waste of resource.

    Hope this makes sense!

    Thursday, August 9, 2012 6:35 PM
  • Frank, great example for using BGW - it has helped me a lot.

    Question, I would like to count the subfolders as they are copied to the destination. Once the process has finished copying I would like to show how many files\ folders were copied and how long it took. I know it's inane but It makes me happy :O)

    I have managed to get a file count and time elapsed but struggling with identifying the folders as they are being copied. I think it is a case of not seeing the wood for the trees.

    I have cheated by calling a sub at the end of your program to recursively ‘get the directories’ of the newly copied destination folder. This does work but I feel it is clumsy and a waste of resource.

    Hope this makes sense!


    Probably the best way would be to modify the program so that you're getting a list of the folders/subfolders, then for each of those, go through the files and copy them. That way you can create a new loop to count folders as you're going through them.

    Please call me Frank :)

    Thursday, August 9, 2012 6:59 PM
  • Ok, on my 'to do' list :O)

    Oh, and one more thing, as columbo would say :O)

    If your program hits a locked or denied file it bombs out at:

     For Each srcFile In My.Computer.FileSystem.GetFiles(sourceFldr, FileIO.SearchOption.SearchAllSubDirectories, "*")
                Try

    Is there a way to catch this error using BGW so I can skip the file? I tried putting the "try" statement the other side of the for each statement but it did not like it at all!

    cheers,


                   


                       





    • Edited by mr do Thursday, August 9, 2012 9:14 PM
    Thursday, August 9, 2012 9:11 PM
  • Is there a way to catch this error using BGW so I can skip the file?

    Yes - we need to test for "safe" folders on the front end.

    It's somewhat involved, and I can't look at it until at least this weekend but you need to start your own question. Refer to this one in your question so everyone knows where we are with this, and if you don't get an answer by this weekend, I'll show you how.


    Please call me Frank :)

    Thursday, August 9, 2012 9:21 PM
  • I have this little application that is using a System.Threading.Thread.Sleep, application runs great but Windows thinks the application is not responding even though it is running.  suggestions on a better or cleaner method, I'm teaching myself so need a little help.  thanks in advance.   

    Imports System.Threading Public Class FormMain Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Try If CheckBoxRepeat.Checked = True Then LabelRepeat.ForeColor = Color.Red Dim var As Integer Dim startVal As Integer Dim endVal As Integer startVal = 1 endVal = (10) For var = startVal To endVal LabelRepeat.Text = (10 & " Times, " & " Sent " & var + 1 & " Times," & " Delay " & 10 & " Seconds.") LabelRepeat.Refresh() System.Threading.Thread.Sleep(10000) Next var

    MsgBox("Done!") End If Catch ex As Exception MsgBox(ex.ToString) End Try End Sub End Class


    I am not sure that someone else has provided this explanation, but here goes:

    The reason windows thinks the application is not responding is because technically, its NOT responding. You have slept the user interface's thread, and when you try to interact with a "busy" thread it is normal behavior for windows to assume the thread is un-responsive. It is standard practice to allow the UI thread to remain responsive by using multi-threads to carry out heavy operations, such as sleep, or loop. So In a nutshell, avoid "sleeping" the user interface thread, instead sleep a multi-threaded non-user interface thread.

    Option Strict On
    Imports System.Threading
    Public Class Form1
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim Th As New Thread(AddressOf Threadwork)
            Th.Start()
        End Sub
        Delegate Sub ChangeLabelText(ByVal Label As Label, ByVal Text As String)
        Delegate Sub RefreshControl(ByVal Control As Control)
        Delegate Sub ChangeLabelForeColor(ByVal Label As Label, ByVal Color As Color)
        Sub UpdateLabel(ByVal Label As Label, ByVal text As String)
            If Label.InvokeRequired Then
                Label.Invoke(New ChangeLabelText(AddressOf UpdateLabel), Label, text)
            Else
                Label.Text = text
            End If
        End Sub
        Sub ControlRefresh(ByVal Control As Control)
            If Control.InvokeRequired Then
                Control.Invoke(New RefreshControl(AddressOf ControlRefresh), Control)
            Else
                Control.Refresh()
            End If
        End Sub
        Sub SetLabelForeColor(ByVal Label As Label, ByVal Color As Color)
            If Label.InvokeRequired Then
                Label.Invoke(New ChangeLabelForeColor(AddressOf SetLabelForeColor), Label, Color)
            Else
                Label.ForeColor = Color
            End If
        End Sub
        Sub Threadwork()
            Try
                If CheckBoxRepeat.Checked = True Then
                    'LabelRepeat.ForeColor = Color.Red
                    SetLabelForeColor(LabelRepeat, Color.Red)
                    Dim var As Integer
                    Dim startVal As Integer
                    Dim endVal As Integer
                    startVal = 1 '
                    endVal = (10)
                    For var = startVal To endVal
                        '   LabelRepeat.Text = (10 & " Times, " & " Sent " & var + 1 & " Times," & " Delay " & 10 & " Seconds.")
                        UpdateLabel(LabelRepeat, 10 & " Times, " & " Sent " & var + 1 & " Times," & " Delay " & 10 & " Seconds.")
                        'LabelRepeat.Refresh()
                        ControlRefresh(LabelRepeat)
                        System.Threading.Thread.Sleep(10)
                    Next var
                    MsgBox("Done!")
                End If
            Catch ex As Exception
                MsgBox(ex.ToString)
            End Try
        End Sub
    End Class


    If you want something you've never had, you need to do something you've never done. If you believe something to be true, then one day you will be called upon to demonstrate that truth.

    Thursday, August 9, 2012 9:51 PM
    Moderator
  • Control.CheckForIllegalCrossThreadCalls = False
    This is a bad practice.

    If you want something you've never had, you need to do something you've never done. If you believe something to be true, then one day you will be called upon to demonstrate that truth.

    Thursday, August 9, 2012 9:55 PM
    Moderator