Alternatives to Thread.Sleep()

Alternatives to Thread.Sleep()

You have to call WaitOne on a WaitHandle, certainly. It's an instance method. Otherwise how would it know what to wait for?

It's definitely better to have something you can react to instead of sleep, so that you can notice cancellation without waiting minutes for no reason. Another alternative to WaitHandle is to use Monitor.Wait/Pulse.

However, if you're using .NET 4 I'd look into what the Task Parallel Library has to offer... it's at a slightly higher level than the other options, and is generally a well thought out library.

For regular work tasks you might want to look at using a Timer (either System.Threading.Timer or System.Timers.Timer) or possibly even Quartz.NET.

Precision alternative to Thread.sleep()

So your solution is not good because of a few issues. You're losing the advantage you gain from using a scheduled executor service by using await await is going to put the current thread to sleep, and then the os will need to schedule it again before it starts.

I've made an example using three different techniques. A spin wait, using thread.sleep and using your scheduled executor idea. The spin wait is the most accurate, at 7002ms where the other two solutions are over 8300ms when finished.

import java.util.concurrent.*;

public class DwellTimes{

static public void spinWait(long ms){
long end = System.nanoTime() + ms*1000000;
long current = System.nanoTime();
while( current < end){
current = System.nanoTime();
}
}

static public void sleepWait(long ms){
try{
Thread.sleep(ms);
} catch(Exception e){
throw new RuntimeException(e);
}
}

static ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);

static public void scheduleWait(long ms){
try{
CountDownLatch l = new CountDownLatch(1);
ses.schedule(l::countDown, ms, TimeUnit.MILLISECONDS);
l.await();
} catch(Exception e){
throw new RuntimeException(e);
}
}



public static void main(String[] args){
long start = System.currentTimeMillis();
for(int i = 0; i<1000; i++){
scheduleWait(7);
}
long end = System.currentTimeMillis() - start;
System.out.println( end + "ms elapsed");
}
}

For a sleep/wait style of flow, the spin wait will be the most accurate because it doesn't release the Thread. It's just going to continue running hot.

The problem with your scheduled executor example is that you're not actually using the scheduling. You want to schedule your tasks.

public static void scheduleWork(){
CountDownLatch latch = new CountDownLatch(1000);
ses.scheduleAtFixedRate(latch::countDown, 7, 7, TimeUnit.MILLISECONDS);
try{
latch.await();
} catch(Exception e){
throw new RuntimeException(e);
}
}

This last example is probably the best way to manage consistent timing because you won't continue to accumulate errors. Eg, if your action takes a couple ms, the next action will not be delayed unless those couple of ms exceed the period.

Is there a alternative to Thread.sleep in java

Is there a alternative to Thread.sleep

Yes, there are ways. But,

It looks like you want to schedule some job. You can either use TimerTask or ScheduledExecutorService instead of this. So later part of your question is about the

"Invoking Thread.sleep in loop can cause performance problems"

and this will solve with scheduling the task.

Scheduling the Task.

public class Test extends TimerTask{

public static void main(String[] args) {
Test task = new Test();
Timer timer = new Timer();
Calendar today = Calendar.getInstance();
today.set(Calendar.HOUR_OF_DAY, 13);
today.set(Calendar.MINUTE, 47);
today.set(Calendar.SECOND, 0);
timer.schedule(task, today.getTime(), TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS));
}

@Override
public void run() {
System.out.println("Running Scheduled Task...!!!");
}
}

Alternative to Thread.Sleep in C#?

Your software would freeze if that sleep is on the main thread. Keep in mind the parameter is in milliseconds. 10 800 000 milliseconds = 10 800 seconds

Another way to pass the time is to pass a TimeSpan object instead. Ex:

// Sleep for 10 seconds
System.Threading.Thread.Sleep(new TimeSpan(0, 0, 10));

As for timer:

You can use System.Timers.Timer;

Timer timer = new Timer();
timer.Interval = 20; // milliseconds
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.AutoReset = true; // if not set you will need to call start after every event fired in the elapsed callback
timer.Start();

Alternatives to using Thread.Sleep for waiting

The WaitHandle type and derived types provide an event-driven mechanism for waiting that ties into the operating system. For example, when you have a Task<T> task and you wait on the result by accessing task.Result, the internal implementation isn't polling with Thread.Sleep calls in between. It's using a WaitHandle-derived type to do waiting and synchronization.

Sometimes a polling-based approach is necessary, as in some of the examples you gave in your bullet list, but often you can use an event-driven approach instead. It's not that Thread.Sleep is always bad - it's just that it is very often misused.

It is just the nature of software to wait for other things in a multi-threaded environment with external factors affecting your code, sometimes you need to wait...

To wait is fine. To wait with polling is often not (*). If there is any way you can use an event-driven wait, you should typically strive to use that.

I don't have a very good feel for exactly what it is that you're asking, so I won't elaborate beyond this. If you leave a comment I can expand my answer.


(*) The theoretical reason waiting with polling is bad is as follows:

Suppose I have code that looks like this:

//START
Begin();
while (!Done())
Thread.Sleep(D);
//STOP

Begin() starts some operation. Done() returning true means the operation has finished. Suppose this will happen after approximately T time. Then:

  • The thread wakes up and checks the condition (calls Done()) T/D times
  • The duration from START to STOP includes an expected D/2 purely because of the Thread.Sleep

What value of D should you choose? As you increase D, the expected duration form START to STOP increases linearly. As you decrease D, the (bound on the) number of iterations increases as 1/D. Both of these are bad, and finding the right D is problematic.

Now compare this to an event-driven wait:

//START
Begin();
WaitDone();
//STOP

Theoretically speaking, as long as WaitDone() somehow magically waits until the operation has finished but no longer, both of the problems identified in the waiting with polling case have disappeared: this thread waits for exactly the right amount of time - no more, no less!

To reiterate the point I started with: in .NET, the WaitHandle class and derived types are what facilitate this approach.

Alternative for Thread.Sleep() to temporarily suspend program

async / await to the rescue:

private async void OnButtonClick(object sender, EventArgs e)
{
listBox1.Items.Clear();
listBox1.Items.Add("3");
await Task.Delay(1000);

listBox1.Items.Add("2");
await Task.Delay(1000);

listBox1.Items.Add("1");
await Task.Delay(1000);

listBox1.Items.Clear();
}

How to interrupt Thread.sleep. Alternatives?

Thread.sleep is non-cancelable and blocks a thread. And spinning on a RunLoop is inefficient. That having been said, there are a few alternatives:

  1. Nowadays, to manage dependencies between asynchronous tasks, we would reach for Swift concurrency’s Task rather than Operation. In Swift concurrency, we have Task.sleep, which, unlike Thread.sleep, is cancelable and does not block the thread.

  2. If you want to stay within OperationQueue patterns, you would use an asynchronous custom Operation subclass (perhaps the AsynchronousOperation shown in either here or here), and then you would use a timer. You could use a DispatchSourceTimer, or a Timer, or asyncAfter with a cancelable DispatchWorkItem. Which you choose really does not matter. The key is to ensure that the cancel implementation invalidates the Timer or cancels the DispatchWorkItem or DispatchSourceTimer, e.g.:

    class OneSecondOperation: AsynchronousOperation {
    weak var timer: Timer?

    override func main() {
    DispatchQueue.main.async {
    self.timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { [weak self] _ in
    self?.finish()
    }
    }
    }

    override func cancel() {
    super.cancel()
    timer?.invalidate()
    finish()
    }
    }

    Note, the pattern whereby you periodically check isCancelled only applies if you have an existing loop. E.g., if you are doing some iterative calculation, for example, that is a very reasonable pattern. But if you are just waiting, the idea of introducing a loop merely to check isCancelled is inefficient. Instead, set up a timer and implement cancel method that cancels that timer, as shown above.

Either way, you want implementation that does not block a thread and can be canceled. With Operation subclass you have to implement that yourself. With Swift concurrency, you get that for free.



Related Topics



Leave a reply



Submit