Comme tout développeur Haxe le sait, vous pouvez utiliser haxe.Timer.delayed()
pour retarder l'appel de fonction pendant un certain temps. Mais cette fonction n'existe pas pour Neko du tout. Y a-t-il un moyen d'atteindre les mêmes résultats?Neko et haxe.Timer.delayed()
Répondre
doivent vérifier d'abord, mais
function delayed(f, time) {
neko.vm.Thread.create(function() {
neko.Sys.sleep(time);
f();
});
}
pourrait être la chose la plus proche possible. Le seul inconvénient est que l'application devient multithread, ce qui peut entraîner de sérieux problèmes.
Oui Je ne sais rien sauf ce que vous mentionnez dans votre première réponse. Sous Linux, vous pouvez utiliser SIGALARM - mais cela ne semble pas trivial, un code C pur à 100%, et doit être manipulé avec beaucoup de soin pour éviter le crash de la VM.
J'ai réfléchi à votre problème et je pense que le meilleur moyen est de créer votre propre classe Timer pour Neko. J'ai fait une classe Timer pour vous:
NekoTimer.hx
package;
import neko.Sys;
class NekoTimer
{
private static var threadActive:Bool = false;
private static var timersList:Array<TimerInfo> = new Array<TimerInfo>();
private static var timerInterval:Float = 0.1;
public static function addTimer(interval:Int, callMethod:Void->Void):Int
{
//setup timer thread if not yet active
if (!threadActive) setupTimerThread();
//add the given timer
return timersList.push(new TimerInfo(interval, callMethod, Sys.time() * 1000)) - 1;
}
public static function delTimer(id:Int):Void
{
timersList.splice(id, 1);
}
private static function setupTimerThread():Void
{
threadActive = true;
neko.vm.Thread.create(function() {
while (true) {
Sys.sleep(timerInterval);
for (timer in timersList) {
if (Sys.time() * 1000 - timer.lastCallTimestamp >= timer.interval) {
timer.callMethod();
timer.lastCallTimestamp = Sys.time() * 1000;
}
}
}
});
}
}
private class TimerInfo
{
public var interval:Int;
public var callMethod:Void->Void;
public var lastCallTimestamp:Float;
public function new(interval:Int, callMethod:Void->Void, lastCallTimestamp:Float) {
this.interval = interval;
this.callMethod = callMethod;
this.lastCallTimestamp = lastCallTimestamp;
}
}
Appelez comme ceci:
package ;
import neko.Lib;
class Main
{
private var timerId:Int;
public function new()
{
trace("setting up timer...");
timerId = NekoTimer.addTimer(5000, timerCallback);
trace(timerId);
//idle main app
while (true) { }
}
private function timerCallback():Void
{
trace("it's now 5 seconds later");
NekoTimer.delTimer(timerId);
trace("removed timer");
}
//neko constructor
static function main()
{
new Main();
}
}
espoir qui aide.
Note: celui-ci a une précision de 100ms. Vous pouvez augmenter cela en diminuant le paramètre timerInterval.
Autant que je soutiens votre effort, cela ne résout rien :) Le rappel sera toujours exécuté dans le contexte de thread différent, celui que vous avez créé dans la classe, car il n'y a aucun moyen de le faire migrer vers le thread principal. – vava
En fait, je me suis rendu compte quand je suis allé au lit ... Je vais poser des questions sur ce problème sur la liste de diffusion haxe. – Tom
J'ai également utilisé la classe, et j'ai trouvé un problème. Parce que ce n'est pas complètement en temps réel, il dort l'intervalle, appelle la fonction et dort de nouveau l'intervalle. Donc, en fonction de la durée de la fonction que vous utilisez, elle est plus lente ou plus rapide.
Je l'ai résolu en remplaçant la ligne 39 comme ceci:
//timer.lastCallTimestamp = Sys.time() * 1000;
timer.lastCallTimestamp = timer.lastCallTimestamp + timer.interval;
Quel genre de problèmes si vous créez seulement un fil à cet effet? – Tom
@Tom, la fonction f() va être exécutée dans le contexte d'un autre thread. Il peut utiliser des ressources partagées ou appeler d'autres fonctions qui utilisent des ressources partagées. Rien de vraiment spécial sur ce cas, juste une application multithread normale. – vava
Dans ce cas, il est probablement préférable de créer l'application Neko avec haXe. Pourquoi ne fais-tu pas ça? – Tom