1

Is it possible to somehow return how many secs there are left on the Thread.Sleep?

Ive tried other ways with a while loop and Thread.Sleep() but never got it to work properly.

Basically i want to update a listview field with how much time there is left

user1213488
  • 473
  • 2
  • 7
  • 19
  • 4
    That's not what Thread.Sleep is for... when a thread sleeps, it can't do anything else. What are you trying to do? It can probably be better achieved with a timer – Thomas Levesque May 10 '12 at 18:32
  • 2
    `Thread.Sleep` is almost always the wrong mechanism. Try using a [`Timer`](http://msdn.microsoft.com/en-us/magazine/cc164015.aspx) instead. – vcsjones May 10 '12 at 18:32
  • 2
    I suppose that when you sleep, you sleep. :) – Steve May 10 '12 at 18:33
  • I want the thread to wait for X seconds and then continue doing the task – user1213488 May 10 '12 at 18:33
  • Thread.Sleep does the job for me so far but i just cant find a way to print the time left to the user – user1213488 May 10 '12 at 18:33
  • 1
    I second the timer comment ... in any case, get the time before and after (but not *from* Thread.Sleep, as Thread.Sleep doesn't provide it) and use that to compute "slept time" and "remaining time" and whatever else is desired. I would use `StopWatch` myself, as it's simple for this. –  May 10 '12 at 18:33
  • Why is Thread.Sleep almost always wrong? – Aaron Deming May 10 '12 at 18:34
  • Can you show me a basic time that would work on threads? I cant seem to understand how to implement a timer – user1213488 May 10 '12 at 18:35
  • @ademing2 [Is Sleep() evil?](http://stackoverflow.com/questions/1096794/is-sleep-evil) – Conrad Frix May 10 '12 at 18:36
  • @user1213488 Can you tell us WHY you want to put the thread to sleep? – General Grey May 10 '12 at 18:43
  • Aside from the limited usefulness of such a mechanism I actually thought this question was interesting. – Brian Gideon May 10 '12 at 20:51
  • 1
    @ConradFrix - no. Misuse of Sleep() is evil. – Martin James May 10 '12 at 21:56
  • @MartinJames: I agree. Not that I would use it willy-nilly, but I really don't see what the big deal is. In fact, sometimes it is the *only* way to do something. Microsoft uses `Thread.Sleep` *extensively* in some of the concurrent BCL classes. Though to be fair those case are *very* narrowly focused. I know you are aware of all that already, but others might not be :) – Brian Gideon May 11 '12 at 04:24
  • @MartinJames I guess I should have written "*See* Is Sleep() evil" in answering the comment "Why is Thread.Sleep almost always wrong" The answers do an Ok of describing why other techniques are preferred and when they're not. – Conrad Frix May 11 '12 at 15:30

3 Answers3

3

While I agree with what vcsjones stated. The best way to do what you request

int millisecondsToSleep=2000;
while (milliseconds>0)
{
    Thread.Sleep(500);
    millisecondsToSleep=millisecondstoSleep-500;
    //alert yourself how much time you have left
    MessageBox.Show(millisecondsToSleep.ToString());
    //do something else if you wish
}

so this will sleep for half a second then send you an alert with how much time is left

As for a timer

            Timer myTimer = new Timer();
            myTimer.Interval = 2000; //2 seconds
            myTimer.Tick += new EventHandler(myTimer_Tick);// fires the myTimer_Tick event every 2 seconds
General Grey
  • 3,598
  • 2
  • 25
  • 32
1

Thread.Sleep is going to stop the thread from executing anything. It's also not perfectly accurate (although I really have no idea of how accurate it is). If you want to put one thread to sleep and then display a field that shows how much time is left; I think the best approach would be to

1.) Sleep one of your threads for X seconds

2.) On your UI thread start a Timer that fires every second for X seconds, do the math and display the estimated time left.

The other alternative I can think of is to have the same thread Sleep and display it's time left; but you'd need to do something like L'Leg suggests.

Maybe I'm misunderstanding what your goal is; but I can't imagine a situation where you'd want either of those behaviours.

If you have work being done in another thread and you want to report how much time is left - maybe take a look at using a BackgroundWorker and using 'ReportProgress'.

Rob P.
  • 14,921
  • 14
  • 73
  • 109
  • 1
    +1. One should treat Thread.Sleep as "absolutely in-accurate" as only guarantee is that wait will not be (much) less than timeout. For small timeouts (0-100) it could mean 100% times difference in actual wait. – Alexei Levenkov May 10 '12 at 18:43
0

Calling Thread.Sleep can sometimes be a code-smell. Without seeing exactly how you are using it I cannot advocate its use in your scenario. But, that aside, the following class might solve your problem. Though, I cannot personally think of a situation where I would ever use this.

public class Sleeper
{
  private TimeSpan remaining = TimeSpan.Zero;

  public TimeSpan GetRemaining()
  {
    lock (this)
    {
      if (remaining > TimeSpan.Zero)
      {
        Monitor.Pulse(this);
        Monitor.Wait(this);
      }
      return remaining;
    }
  }

  public void Sleep(TimeSpan timeout)
  {
    lock (this)
    {
      if (remaining > TimeSpan.Zero)
      {
        throw new InvalidOperationException("Sorry, but I'm not safe for multiple sleepers.");
      }
      remaining = timeout;
      DateTime expires = DateTime.UtcNow.Add(remaining);
      bool complete = remaining <= TimeSpan.Zero;
      while (!complete)
      {
        bool complete = Monitor.Wait(this, remaining);
        remaining = expire - DateTime.UtcNow;
        if (remaining <= TimeSpan.Zero)
        {
          complete = true;
        }
        if (complete)
        {
          remaining = TimeSpan.Zero;
        }
        Monitor.Pulse(this);
      }
    }
  }
}

And then use it like this.

public static void Main()
{
  var sleeper = new Sleeper();

  Task.Factory.StartNew(
    () =>
    {
      while (true)
      {
        sleeper.Sleep(TimeSpan.FromMinutes(1);
      }
    });

  while (true)
  {
    Console.WriteLine("Press ENTER to get time remaining...");
    Console.ReadLine();
    TimeSpan remaining = sleeper.GetRemaining();
    Console.WriteLine("Remaining = " + remaining.ToString());
  }
}

Again, there are only a few scenarios where I can imagine that this might be useful. I suppose a more sophisticated variation of a latch that is focused more on timing might be useful. The principals of how it would work would be very similar to what I created above. You might call it a "timed latch" which could also report its due time to any interested callers.

Brian Gideon
  • 47,849
  • 13
  • 107
  • 150