在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);elselua_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机制来防止脚本的阻塞,这个方法下次再说了。。。
http://www.cnblogs.com/roucheng/p/suanfa4.html
看不见我将要去的地方,记不得我已经去过的地方。