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