Timeout on a Function Call

Timeout on a function call

You may use the signal package if you are running on UNIX:

In [1]: import signal

# Register an handler for the timeout
In [2]: def handler(signum, frame):
...: print("Forever is over!")
...: raise Exception("end of time")
...:

# This function *may* run for an indetermined time...
In [3]: def loop_forever():
...: import time
...: while 1:
...: print("sec")
...: time.sleep(1)
...:
...:

# Register the signal function handler
In [4]: signal.signal(signal.SIGALRM, handler)
Out[4]: 0

# Define a timeout for your function
In [5]: signal.alarm(10)
Out[5]: 0

In [6]: try:
...: loop_forever()
...: except Exception, exc:
...: print(exc)
....:
sec
sec
sec
sec
sec
sec
sec
sec
Forever is over!
end of time

# Cancel the timer if the function returned before timeout
# (ok, mine won't but yours maybe will :)
In [7]: signal.alarm(0)
Out[7]: 0

10 seconds after the call signal.alarm(10), the handler is called. This raises an exception that you can intercept from the regular Python code.

This module doesn't play well with threads (but then, who does?)

Note that since we raise an exception when timeout happens, it may end up caught and ignored inside the function, for example of one such function:

def loop_forever():
while 1:
print('sec')
try:
time.sleep(10)
except:
continue

How to wait for setTimeout before each function call?

Since this question is marked with typescript I'm going to asume that writing this in Typescript is an option.

You could use async/await to easily achieve the effect you want while your code maintains a normal look:

var myVar;

async function call(){
await myFunction('normal1', 'heading1', 'message1');
await myFunction('normal2', 'heading2', 'message2');
await myFunction('normal3', 'heading3', 'message3');
}
function timeout(delay: number) {
return new Promise(r => setTimeout(r, delay));
}
async function myFunction(msgType: string, heading: string, message: string) {
console.log(!!document.getElementById("snackbarParent"), document.getElementById('snackbarParent'));
if (document.getElementById("snackbarParent") == null) {
await alertFunc(msgType, heading, message);
}
else {
await timeout(3500);

let parent = document.getElementById('snackbarParent');
parent.parentNode.removeChild(parent);
await alertFunc(msgType, heading, message);

}
}

async function alertFunc(msgType, heading, message) {

let div = document.createElement('div');
div.className = 'snackbarParent';
div.id = "snackbarParent";
div.innerHTML = '<div id="snackbar"><b style="color:' + msgType + '"> ' + heading + ' </b>' + message + '</div>';

document.documentElement.appendChild(div);
// Get the snackbar DIV
let x = document.getElementById("snackbar");

// Add the "show" class to DIV
x.className = "show";
await timeout(3000);
x.className = x.className.replace("show", "");
alert("Should display " + heading + " " + message + " now!");

}

Note: If you don't want typescript, babel also has support for async/await but you will still need a transpiler.

Note To compile for es5 with async/await you will need a Priomise library if promises aren't in the environment, and you can use the flowing tconfig.json:

"compilerOptions": {
"target": "es5",
"lib": [
"es5",
"es2015.promise",
"dom"
]
}

A pure js approach could use an onDone callback to have a way to notify the caller of when the function really completed. This is better that to add the code directly in alertFunc as other answers suggest as that will make alertFunc less reusable:

function call() {
myFunction('normal1', 'heading1', 'message1', function () {
myFunction('normal2', 'heading2', 'message2', function () {
myFunction('normal3', 'heading3', 'message3', function () {
// DOne
});
});
});
}
function myFunction(msgType, heading, message, onDone) {
console.log(!!document.getElementById("snackbarParent"), document.getElementById('snackbarParent'));
if (document.getElementById("snackbarParent") == null) {
alertFunc(msgType, heading, message, onDone);
}
else {
setTimeout(function () {
var parent = document.getElementById('snackbarParent');
parent.parentNode.removeChild(parent);
alertFunc(msgType, heading, message, onDone);
}, 3500);
}
}
function alertFunc(msgType, heading, message, onDone) {
var div = document.createElement('div');
div.className = 'snackbarParent';
div.id = "snackbarParent";
div.innerHTML = '<div id="snackbar"><b style="color:' + msgType + '"> ' + heading + ' </b>' + message + '</div>';
document.documentElement.appendChild(div);
// Get the snackbar DIV
var x = document.getElementById("snackbar");
// Add the "show" class to DIV
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
alert("Should display " + heading + " " + message + " now!");
if (onDone)
onDone();
}, 3000);
}

Generically timeout a function call (without Task/CancellationToken)

I agree with everybody saying that using Tasks is better and CancellationToken, but rewriting all the legacy code in order to comply would be too time consuming.

I actually found a solution to my context problem thanks to Access session data from another thread

So here is my final solution :

Public Function CallWithTimeOut(Of T)(timeOut As Integer, dlg As Func(Of T), Optional ByVal ctx As System.Web.HttpContext = Nothing) As T
Dim ret As T

Dim th As Thread

th = New Thread(New ThreadStart(Sub()
If Not ctx Is Nothing Then
System.Web.HttpContext.Current = ctx
End If
ret = dlg.Invoke()
End Sub))

th.Start()
th.Join(timeOut)
If th.IsAlive Then
th.Abort()
Throw New TimeoutException
End If

Return ret
End Function

Cancel timout / timer if function called again --- debounce function

setTimeout returns an id you can use to clear that timeout with clearTimeout(). So you can clear the existing timeout at the beginning of your function.

For example if you keep clicking it will keep restarting -- if you don't click it finishes in 2 seconds:

let timerID;
function setTimer() { console.log("starting/restarting timer") clearTimeout(timerID) timerID = setTimeout(() => { console.log("finished") }, 2000)}
<p onclick="setTimer()">click to start</p>

Making function call stop after given time budget

You can use a subprocess for each function call. The subprocess.run() method accepts a timeout parameter that is the number of seconds the until the child is killed. From the docs:

The timeout argument is passed to Popen.communicate(). If the timeout expires, the child process will be killed and waited for. The TimeoutExpired exception will be re-raised after the child process has terminated.

So its necessary to handle TimeoutExpired exceptions that will be thrown if any of the processes do end up exceeding the timeout limit.

Another option is to use signals to set timers and send a SIGLARM. This has the advantage of being a little less destructive, since you can modify the called functions to properly handle the signal when it comes, giving them a chance to shutdown cleanly. The downside is that signals can be tricky to program, whereas the subprocess option is a pretty self-contained solution right out of the box.

Setting timeout for c/c++ function call

You can call this function in a new thread, and set a timeout to terminate the thread, it will end this function call.

A POSIX example would be:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>

pthread_t tid;

// Your very slow function, it will finish running after 5 seconds, and print Exit message.
// But if we terminate the thread in 3 seconds, Exit message will not print.
void * veryslow(void *arg)
{
fprintf(stdout, "Enter veryslow...\n");
sleep(5);
fprintf(stdout, "Exit veryslow...\n");

return nullptr;
}

void alarm_handler(int a)
{
fprintf(stdout, "Enter alarm_handler...\n");
pthread_cancel(tid); // terminate thread
}

int main()
{
pthread_create(&tid, nullptr, veryslow, nullptr);

signal(SIGALRM, alarm_handler);
alarm(3); // Run alarm_handler after 3 seconds, and terminate thread in it

pthread_join(tid, nullptr); // Wait for thread finish

return 0;
}

function call within setTimeout not executing

That is because these, this inside the callback, does not refer to the object outside.

Try this:

delayFilter() {
let timeout = null;
clearTimeout(timeout);
let self = this;
timeout = setTimeout(function() {
self.filterProducts();
}, 1000);
}

filterProducts() {
//do stuff
}

You can also try the arrow function. The reason can be seen here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

An arrow function expression is a syntactically compact alternative to a regular function expression, although without its own bindings to the this, arguments, super, or new.target keywords.

delayFilter() {
let timeout = null;
clearTimeout(timeout);
timeout = setTimeout(() => {
this.filterProducts();
}, 1000);
}

filterProducts() {
//do stuff
}

How to callback function in set timeout node js

You must wrap your calls to getData in an anonymous function, e.g. setTimeout(function(){ getData(x, y, …) }, 1000).



Related Topics



Leave a reply



Submit