首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >终止NLua脚本执行

终止NLua脚本执行
EN

Stack Overflow用户
提问于 2020-06-19 04:32:06
回答 1查看 454关注 0票数 0

我正在使用NLua在我的应用程序中运行Lua脚本。我需要实现在任何时候终止运行在单独线程中的脚本的能力,例如用户按下“停止”按钮,脚本必须立即终止。我读过关于SetDebugHook的文章,并试图关闭Lua并调用状态上的错误,但我总是得到AccessViolationException。

我试过了

代码语言:javascript
复制
Lua env = new Lua(); // created in main thread
env.DoString(); // called in second thread

// Called in main thread
public void Stop()
{
    env.Close(); // Didn't work. AccessViolationException
    env.State.Close(); // Didn't work. AccessViolationException
    env.State.Error("err"); // Didn't work. AccessViolationException
}

尝试将线程与锁同步

代码语言:javascript
复制
lock (locker)
{
    if (env.IsExecuting)
        env.Close();
}

同样的问题。AccessViolationException

谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-19 22:32:11

该方法工作得相当好,在执行每一行lua代码之前,使用lua_sethook检查要中止的信号:

代码语言:javascript
复制
public partial class NluaThreading : Form
{
    private Lua state;
    private bool abort;
    public NluaThreading()
    {
        InitializeComponent();
    }

    private void Start_Click(object sender, EventArgs e)
    {
        state = new Lua();
        state.SetDebugHook(KeraLua.LuaHookMask.Line, 0);
        state.DebugHook += State_DebugHook;

        abort = true; //force abort after first debughook event

        new Thread(DoLua).Start();
    }

    private void State_DebugHook(object sender, NLua.Event.DebugHookEventArgs e)
    {
        if (abort)
        {
            Lua l = (Lua)sender;
            l.State.Error("Execution manually aborted");
        }
    }
    private void DoLua()
    {
        try
        {
            state.DoString("while(true) do end");
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message, "DoLua", MessageBoxButtons.OK);
        }
    }
}

当然,这是以每一行增加一些开销为代价的,以减少您可以更改其他值之一的挂钩。

另一个选项是使用lua线程将监视的令牌,然后根据需要中止,此方法确实需要在lua脚本中进行一些处理:

代码语言:javascript
复制
public partial class NluaThreading : Form
{
    internal class Tokens
    {
        public bool abort = false;
    }

    private Lua state;
    private Tokens tokens;

    public NluaThreading()
    {
       InitializeComponent();

       state = new Lua();
       tokens = new Tokens();
       state["tokens"] = tokens; //now the tokens are visible inside the lua
                                 //environment and will reflect changes we make 
                                 //from the main thread
    }

    private void Start_Click(object sender, EventArgs e)
    {
        if (!state.IsExecuting)
        {
            tokens.abort = false;
            new Thread(DoLua).Start();
        }
    }

    private void Stop_Click(object sender, EventArgs e) => tokens.abort = true;

    private void DoLua() => state.DoString("repeat print(tokens.abort) until(tokens.abort); print(tokens.abort)");
}

现在,您的lua执行通常会更加复杂,包含许多嵌套循环,在这些情况下,您可以在lua中实现一个函数来检查令牌,并在令牌为真时抛出一个错误:

代码语言:javascript
复制
function checkTokens()
    if tokens.abort then
        error('Execution manually aborted')
    end
end

加载到lua状态后,我们应该对DoLua函数进行一些更改:

代码语言:javascript
复制
private void DoLua()
{
    try
    {
        state.DoString("while(true) do print(tokens.abort); checkTokens(); end");
    }
    catch(Exception e)
    {
        MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK);
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62463286

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档