前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Lua使用心得(2)

Lua使用心得(2)

作者头像
全栈程序员站长
发布2022-07-15 16:11:48
4330
发布2022-07-15 16:11:48
举报

大家好,又见面了,我是全栈君

在lua脚本调用中,如果我们碰到一种不好的脚本,例如:

while 1 do

do

end

那我们的程序主线程也会被阻塞住。那我们如何防止这种问题呢?下面就给出一个解决的办法。

首先为了不阻塞主线程,那我们就要开一个线程,把处理脚本的操作都放在这个新开的工作线程里。(要详细了解工作线程和界面线程的区别和管理,请参看本人的另一篇文章BLOG下Windows编程里的《Windows 线程漫谈——界面线程和工作者线程》)。

总体思路:

1、开线程来执行脚本解析,下面是StartRun()

2、导出一个判断是否结束函数,让脚本每个循环都调用,判断线程是否该结束了,这个函数在下面是IsThreadExit(),返回一个字符串(”exit” 表示while循环该结束了,”Notexit” 表示线程还不能结束)

3、如果主线程需要主动结束线程,就调用StopRun()

4、最好导出一个 ySleep 停顿函数,以免while循环里执行太快,导致CPU被高占用。http://hovertree.com/

按照这种思路,lua脚本变成如下形式:

while 1 do

exitThread=IsThreadExit(); ySleep(100);

if exitThread == “exit” then break; end;

end;

VC代码如下,其中的Output是一个输出函数,你可以用MessageBox来代替:

// 全局变量

// 标志线程是否要结束 BOOL g_bExitDofile = FALSE; // 线程句柄 HANDLE g_hDofile = NULL;

// 需要导出的函数

// 让 Lua 判断循环是否可以退出 static int IsThreadExit(lua_State* L) { if(g_bExitDofile) lua_pushlstring(L, “exit”, 4); else lua_pushlstring(L, “Notexit”, 7); // 一个返回值 return 1; }

// 停顿函数

int ySleep(lua_State* L) { int d = luaL_checkinteger(L, 1); Sleep(d); return 0; }

// 注册以上函数

int RegFunc()

{ lua_pushcfunction(g_pLua, IsThreadExit); lua_setglobal(g_pLua, “IsThreadExit”); lua_pushcfunction(g_pLua, ySleep); lua_setglobal(g_pLua, “ySleep”);

return 0;

}

// 线程函数

DWORD WINAPI DofileThread(LPVOID lpParam) { LPCTSTR strFilePath = (LPCTSTR)lpParam; luaL_dofile(g_pLua, strFilePath); StackDump(g_pLua); return 0; }

// 线程启动

int StartRun(LPCTSTR strFilePath) {

// 注册所有需要导出的函数 RegFunc();

if(g_hDofile == NULL) { // 创建线程来执行LUA脚本 g_hDofile = CreateThread(NULL, 0, DofileThread, (LPVOID)strFilePath, 0, NULL); } else { Output(“请先调用StopRun()”); }

return 0; }

// 停止线程

int StopRun() { // 如果线程正在跑 if(g_hDofile) { // 给lua循环结束的信号 g_bExitDofile = TRUE; // 等待线程退出 DWORD dwRet = WaitForSingleObject(g_hDofile, INFINITE); // 如果顺利退出 if(dwRet == WAIT_OBJECT_0) { CloseHandle(g_hDofile); g_hDofile = NULL; g_bExitDofile = FALSE; Output(“Dofile thread exited!”); } // 否则强硬杀掉线程 else { DWORD dwExitCode; GetExitCodeThread(g_hDofile, &dwExitCode);

TerminateThread(g_hDofile, dwExitCode);

g_hDofile = NULL; g_bExitDofile = FALSE; Output(“Dofile thread was killed!”); } }

return 0; }

上面这个方法是利用了线程的本身特性解决掉脚本阻塞的问题。还可以使用LUA本身的HOOKS机制来防止脚本的阻塞,这个方法下次再说了。。。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/120442.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021年12月,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档