Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 终止NLua脚本执行_C#_Lua_Terminate_Nlua - Fatal编程技术网

C# 终止NLua脚本执行

C# 终止NLua脚本执行,c#,lua,terminate,nlua,C#,Lua,Terminate,Nlua,我正在使用NLua在我的应用程序中运行Lua脚本。我需要实现随时终止在单独线程中运行的脚本的能力,例如,用户按下“停止”按钮,脚本必须立即终止。我读过关于SetDebugHook的文章,试图关闭Lua状态并在状态上调用Error,但我总是得到AccessViolationException 我试过了 Lua env = new Lua(); // created in main thread env.DoString(); // called in second thread // Calle

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

我试过了

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
}
试图用锁同步线程

lock (locker)
{
    if (env.IsExecuting)
        env.Close();
}
同样的问题。AccessViolationException


谢谢。

此方法相当有效,在执行每行lua代码之前,使用
lua\u sethook
检查要中止的信号:

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脚本中进行一些处理:

public分部类NluaThreading:表单
{
内部类标记
{
公共布尔中止=假;
}
私有Lua国家;
私人代币代币;
公共NluaThreading()
{
初始化组件();
state=新的Lua();
令牌=新令牌();
state[“tokens”]=tokens;//现在这些token在lua中可见
//环境将反映我们所做的改变
//从主线
}
私有无效开始\单击(对象发送者,事件参数e)
{
如果(!state.IsExecuting)
{
tokens.abort=false;
新线程(DoLua.Start();
}
}
private void Stop_Click(对象发送方,EventArgs e)=>tokens.abort=true;
私有void DoLua()=>state.DoString(“重复打印(tokens.abort)直到(tokens.abort);打印(tokens.abort)”;
}
现在,您的lua执行通常会更加复杂,包含许多嵌套循环,在这些情况下,您可以在lua中实现一个函数来检查令牌,并在令牌为true时抛出错误:

函数checkTokens()
如果tokens.abort,则
错误('手动中止执行')
终止
终止
加载到lua状态后,我们应该对
DoLua
函数进行一些更改:

private void DoLua()
{
尝试
{
state.DoString(“while(true)do print(tokens.abort);checkTokens();end”);
}
捕获(例外e)
{
MessageBox.Show(例如Message,“Error”,MessageBox按钮.OK);
}
}

您需要发布您尝试过的代码。我发布了一些代码,但它们都不起作用,每次都是同一个问题,AccessViolationException我使用
Nlua有类似的需求
我设置了一个变量,当操作员按下
ABORT
按钮时,我会将该变量设置为true=this.abort此变量是在代码占用大部分时间的代码最低函数中检查的。未“立即”检测到压力机,但在0-250ms之后,该特定系统还配备了一个硬件紧急停止装置,在按下时切断系统电源,所有需要停止的系统都应该有一个硬件停止装置,因为软件永远不会100%可靠,输入设备是否损坏,pc是否冻结,等等。我需要终止NLua脚本执行,但不声明任何变量,并使用现在正在执行的Lua代码检查,纯C#。所以,如果代码执行并且用户按下“停止”按钮,脚本应该立即终止,它可以延迟终止,但最好是在它可以终止线程时立即终止。我不需要终止线程本身,我只需要终止在该脚本中运行的脚本,脚本终止后线程将正常退出。不,这不是工厂生产设施,它只是一个模拟脚本环境的应用程序。而且,我需要尽可能地在没有任何Lua代码的情况下实现它。但Lua代码的执行方式与您编写更新的答案的执行方式相同,以提供一个不需要Lua代码的选项。很抱歉,响应时间太长,在此期间我正在做其他事情,但这确实帮助了我,并且做了我所期望的事情(我正在使用DebugHooks)。谢谢