Этот метод работает достаточно хорошо, используя lua_sethook
для проверки сигнала на прерывание перед выполнением каждой строки кода lua:
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 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 для проверки токены и выдает ошибку, когда токен истинен:
function checkTokens()
if tokens.abort then
error('Execution manually aborted')
end
end
с загруженным в состояние lua, мы должны внести некоторые изменения в функцию DoLua
:
private void DoLua()
{
try
{
state.DoString("while(true) do print(tokens.abort); checkTokens(); end");
}
catch(Exception e)
{
MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK);
}
}