17

Hi I am trying to find a method of waiting a number of milliseconds before moving to the next line of code,

I have looked into Thread.Sleep but this will freeze the main form, I would like this to remain active.

I tried timers and stopwatches and both freeze the main form when they should be posting to a console when they tick.

I couldn't find a way of using task.delay or background worker in the wait I wanted either.

Pseudo Code:

Wait 2 - 6 seconds
Log "waiting"
Log "waiting"
Log "waiting"
Stop Waiting - Run next line of code.

The methods I have tried just freeze up the form and fill the log afterwards, I just want a simple method of waiting without freezing the form and without having to deal with events being called which would mean the next line isn't run.

Any help would be awesome because I am still new to c# and its been driving me a bit mad :(

Davin Tryon
  • 66,517
  • 15
  • 143
  • 132
Someone
  • 894
  • 3
  • 22
  • 43

4 Answers4

28

The await keyword, in conjunction with Task.Delay makes this trivial.

public async Task Foo()
{
    await Task.Delay(2000);
    txtConsole.AppendText("Waiting...");
    DoStuff();
}
Servy
  • 202,030
  • 26
  • 332
  • 449
  • Thanks this is all I needed, I had tried the Task.Delay but I wasn't aware of having to use it in conjunction with "async Task" and "await" – Someone Apr 14 '13 at 19:14
  • 4
    @Sam You certainly don't *have* to. You could use `Task.Delay(2000).ContinueWith(t=>DoStuff(), ..., Task.Factory.FromCurrentSynchronizationContext());` instead, which is what the `await` will refactor it into eventually. – Servy Apr 14 '13 at 19:16
  • @Servy how would you go about this in .Net4.0 ? – Arvo Bowen Apr 26 '16 at 16:34
  • @ArvoBowen You'd use `ContinueWith` instead of `await`. If you want good error handling semantics it's a bit more work, but other than handling errors you'd just put the rest of the code in the continuation and it wouldn't be that bad. – Servy Apr 26 '16 at 16:48
  • @Servy so then I guess it will be `Task.Factory.StartNew(() => DoStuffStart(), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).ContinueWith((t) => DoStuffFinished(t.Result));` for me. ;) – Arvo Bowen Apr 26 '16 at 18:38
  • Task.Delay() could bring concurrency problems since it's yielding the execution. –  Aug 13 '18 at 13:59
  • 1
    @IamDOM The code is all running in the UI thread, so there's nothing running concurrently. Yes, other UI events may run between invocations of `DoStuff`. It will need to be written to support that. I see no indication from the question that it isn't. Nor is there really any alternatives. – Servy Aug 13 '18 at 14:01
  • I've forgotten to take the question in context. My bad. –  Aug 13 '18 at 14:03
2

Try using a DispatcherTimer. It's a pretty handy object that does all the work of delegating to the UI thread.

For example:

private DispatcherTimer _dtTimer = null;

public Constructor1(){
  _dtTimer = new DispatcherTimer();
  _dtTimer.Tick += new System.EventHandler(HandleTick);
  _dtTimer.Interval = new TimeSpan(0, 0, 0, 2); //Timespan of 2 seconds
  _dtTimer.Start();
}

private void HandleTick(object sender, System.EventArgs e) {
  _uiTextBlock.Text = "Timer ticked!";
}
Daniel
  • 10,864
  • 22
  • 84
  • 115
-1

Timer should work fine in this case, unless you put Thread.Sleep in its handler or the handler itself takes too much time to complete.

You haven't specified the UI framework that you use or .Net version, but for the latest .Net you can use async/await. That way, UI would not be frozen while your code awaits for the background task

void async MyMethod()
{  
    var result = await Task.Run(() => long_running_code);
}
alex
  • 12,464
  • 3
  • 46
  • 67
-1
DateTime Tthen = DateTime.Now;
            do
            {
                Application.DoEvents();
            } while (Tthen.AddSeconds(5) > DateTime.Now);