Neko和haxe.Timer.delayed()

3

正如每个Haxe开发者所知,你可以使用haxe.Timer.delayed()来延迟函数的调用。但是,对于Neko来说,这个函数根本不存在。有没有一种方法可以实现相同的结果?

4个回答

4

首先需要检查它,但是

function delayed(f, time) {
   neko.vm.Thread.create(function() {
       neko.Sys.sleep(time);
       f();
   });
}

也许这是最接近实现的方法了。唯一的缺点是应用程序变成了多线程,可能会导致严重的问题。


如果只为此目的创建一个线程会有什么问题? - Tom
@Tom,函数f()将在另一个线程的上下文中执行。它可能会使用共享资源或调用其他使用共享资源的函数。这种情况并没有什么特别之处,只是正常的多线程应用程序。 - vava
在这种情况下,最好使用haXe创建Neko应用程序。你为什么不这样做呢? - Tom
@Tom,我做到了 :) 但是在neko或php下,haxe.Timer只有一个方法stamp()delayed()在所有其他平台上都可用,但在neko中不可用。 - vava
啊,我明白了。在这种情况下,我建议你为neko创建自己的计时器类。静态构造函数将创建一个新线程,该线程以特定间隔简单地循环,跟踪时间戳并注册新添加的计时器。祝你好运。如果你打算这样做,如果你能与haXe社区分享这个类,那就太好了。 - Tom

1

我考虑了你的问题,我认为最好的方法是为 Neko 创建自己的计时器类。我为你创建了一个 Timer 类:

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;
    }
}

这样调用:

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();
    }
}

希望能有所帮助。 注意:这个准确率为100毫秒。你可以通过减少timerInterval设置来增加它。

尽管我支持你的努力,但这并不能解决任何问题 :) 回调仍将在不同线程的上下文中运行,因为你在类中创建了它,没有办法将其迁移到主线程。 - vava
其实我是在睡觉前意识到这个问题的... 我打算在haxe邮件列表上询问这个问题。 - Tom

1
我也使用了这个类,但发现了一个问题。因为它不是完全实时的,它会等待一段时间,调用函数,然后再等待一段时间。所以,取决于你运行的函数需要多长时间,它的速度可能会变慢或变快。
我通过将第39行替换为以下内容来解决这个问题:
//timer.lastCallTimestamp = Sys.time() * 1000;
timer.lastCallTimestamp = timer.lastCallTimestamp + timer.interval;

0

是的,除了你在第一个答案中提到的内容,我什么也不知道。在Linux上,您可以使用SIGALARM - 但这看起来并不容易,需要100%纯C代码,并且需要非常小心地处理以避免崩溃VM。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接