10

I googled for this and read some threads here, but I haven't found a simple way to have a VB.Net application sleep for a little while and still keep the application responsive:

Imports System.Net
Imports System.IO
Imports System.Text
Imports System.Text.RegularExpressions
Imports System.Threading.Thread

[...]

''#How to keep screen frop freezing?
While True
  ListBox1.Items.Clear()

  ListBox1.Items.Add("blah")

  ''#Not much difference
  ListBox1.Refresh()

  ''#Wait 1mn
  Sleep(60000)
End While

Is there really no simple, non-blocking solution to have a VB.Net application wait for a few seconds?

Thank you.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
Gulbahar
  • 5,343
  • 20
  • 70
  • 93
  • 1
    What is the purpose of the sleep? You either want it to sleep, or you want it to be responsive. If what you are trying to do is something that occurs at scheduled intervals, then say so. – dbasnett Feb 10 '10 at 14:53
  • I'm screen scraping a web page every minute, and would like the application to pause every minute without the application screen freezing. Is it still OK to use DoEvents or is it recommended to use a Timer instead? – Gulbahar Feb 10 '10 at 15:01
  • @OverTheRainbow - See nikie's comment below. Sounds like you're best off with a timer. – Seth Moore Feb 10 '10 at 15:20
  • Thanks guys, I'll use a Timer instead. – Gulbahar Feb 10 '10 at 15:23
  • Do make sure that you know what happens when one iteration takes more than one timer interval though. You could end up with two Timer-Event functions running at the same time (although the old VB5 timers prevented that automatically I think). – Wim Feb 10 '10 at 15:57
  • Yeah, def disable the timer before you start your routines, then re-enable it afterwards to prevent interval overlap. This will make your actual interval = timerInterval+routineRuntime, so it could be longer that you anticipate. – Seth Moore Feb 10 '10 at 16:12
  • @OverTheRainbow - Did using the Timer work for what you wanted? – Seth Moore Feb 10 '10 at 16:47
  • I tried all most of the methods provided here. They all caused me problems **except** for the timer method which worked great. – Off The Gold Oct 09 '15 at 14:03

8 Answers8

8
Public Sub ResponsiveSleep(ByRef iMilliSeconds As Integer)
    Dim i As Integer, iHalfSeconds As Integer = iMilliSeconds / 500
    For i = 1 To iHalfSeconds
        Threading.Thread.Sleep(500) : Application.DoEvents()
    Next i
End Sub

Call ResponsiveSleep to pause a particular piece of code whilst keeping the application fairly responsive. To make the application more responsive iHalfSeconds could be modified to tenths or hundredths of a second

user408874
  • 81
  • 1
  • 2
  • 1
    This method used less CPU resources than the Stopwatch. – rsrobbins Apr 17 '14 at 13:03
  • 2
    I've had problems with `Application.DoEvents()`. See [here](https://social.msdn.microsoft.com/Forums/vstudio/en-US/48b4a763-7387-46da-8fc2-3e885670f62c/the-undo-operation-encountered-a-context-that-is-different?forum=netfxbcl), for example. – darda Jun 28 '15 at 17:42
  • is that `:` construction something VB-specific? How would that look in c#? – Nyerguds Nov 04 '16 at 14:05
7

Is this WinForms or WPF?

If it's WinForms you could just use a timer instead of a while loop. Then your app would still be responsive and raise events.

In WPF I think you would have to make your own timer based on the DispatchTimer class.

Seth Moore
  • 3,575
  • 2
  • 23
  • 33
  • Aren't there timers in WPF also? – CoderDennis Feb 10 '10 at 14:56
  • I just opened a project really quick and didn't see any Timer controls in the designer, so there very well might be, I've just never needed to use one in WPF. A quick search on google makes me think though that it's not available (http://social.msdn.microsoft.com/forums/en-US/wpf/thread/aaffea95-e735-492d-bd8a-2fdf7099a936/). – Seth Moore Feb 10 '10 at 15:07
  • It doesnt have to be a control does it? You can use System.Timers.Timer or System.Threading.Timer in the code. – Ravi Y Nov 26 '12 at 16:45
5

How about this simple piece of code - :)

Private Async Sub Button10_Click(sender As Object, e As EventArgs) Handles Button10.Click
        MsgBox("This msgbox is shown immidiatly. click OK and hover mouse over other controls to see if UI is freezed")
        Await Task.Delay(5000)
        MsgBox("see? UI did'nt freez :). Notice the keyword 'Async' between Private and Sub")
    End Sub

Use Async on declared sub and then put Await Task.Delay(milliseconds) instead of Thread.Sleep(milliseconds)

MbPCM
  • 457
  • 5
  • 12
4
Private Sub wait(ByVal interval As Integer)
    Dim stopW As New Stopwatch
    stopW.Start()
    Do While stopW.ElapsedMilliseconds < interval
        ' Allows your UI to remain responsive
        Application.DoEvents()
    Loop
    stopW.Stop()
End Sub
Gbolahan
  • 420
  • 2
  • 8
  • 18
3

Really, the solution is two fold: 1.) Use a timer instead of sleeping, sleep does as it says, causes the thread to sleep. 2.) Use multi-threading and have your screen scrapping function run in it's own thread, this will greatly enhance the responsiveness of your application.

Threading.Thread.Sleep(IntSleepTime)

Is a thread safe sleep function that will pause the current thread for the specified time, so if you were to use sleep, you can do so in a multi-threading environment and it will keep the rest of your app responsive as you're only sleeping a branched thread, not the main thread.

Jarrod Christman
  • 380
  • 2
  • 19
1

The Timer suggestion is really the best way to do it. But if DoEvents still works (I haven't done VB since 5.0), you can do this:

For i = 0 To 600
    DoEvents
    Sleep(100)
Next

This would do 600 sleeps of .1 second each, with a DoEvents between each to handle current events. The .1 second should be a good tradeoff between responsiveness (events get handled within .1 second) and CPU consumtion (do this too fast and your app will start consuming a significant amount of CPU time even while waiting).

Wim
  • 11,091
  • 41
  • 58
  • Dear downvoter, while I respectfully accept your downvote, would you consider leaving a comment with which I could improve my answer? Thanks. – Wim Feb 10 '10 at 14:55
  • I don't know why this was downvoted either. The functions are called Application.DoEvents and Thread.Sleep in .NET, but anyone with an up to date MSDN would have found that out. It should be pointed out that DoEvents can lead to all kinds of weird behavior (e.g. if the form is closed while the function is running or if DoEvents calls the same function again.) But you did say that it's not the ideal way to do that. – Niki Feb 10 '10 at 15:05
  • 1
    I'm not the downvoter, but DoEvents is not good practice. It causes issues if the method is not correctly written to account for re-entry. – Joel Coehoorn Aug 02 '10 at 17:09
0

U are make the UI Thread Which handing the form to sleep. If u want to make ur application responsive,first make a method which add the items in list view and when ur form loads start that method using thread,now use sleep to make ur list view thread sleep,and ur from will be in responsive state..

0

This is for VB not VBA

    Private Async Function PauseTime(ByVal MS As Integer) As Task

    Await Task.Run(Sub()                         
                           Thread.Sleep(MS)

                   End Sub)


     End Function
Jimva
  • 36
  • 6