在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机制来防止脚本的阻塞,这个方法下次再说了。。。

http://www.cnblogs.com/roucheng/p/suanfa4.html

Lua使用心得(2)的更多相关文章

  1. <转> Lua使用心得(2)

    在lua脚本调用中,如果我们碰到一种不好的脚本,例如: do do end 那我们的程序主线程也会被阻塞住.那我们如何防止这种问题呢?下面就给出一个解决的办法. 首先为了不阻塞主线程,那我们就要开一个 ...

  2. Lua使用心得(1)

    这几天研究了一下lua,主要关注的是lua和vc之间的整合,把代码都写好放在VC宿主程序里,然后在lua里调用宿主程序的这些代码(或者叫接口.组件,随便你怎么叫),希望能用脚本来控制主程序的行为.这实 ...

  3. (转) Lua使用心得一 LUA和VC整合

    这几天研究了一下lua,主要关注的是lua和vc之间的整合,把代码都写好放在VC宿主程序里,然后在lua里调用宿主程序的这些代码(或者叫接口.组件,随便你怎么叫),希望能用脚本来控制主程序的行为.这实 ...

  4. JS在与lua的交互心得

    最近在写一个项目,前端技术使用的是Vue,在与lua的交互过程,是通过一个公共JS,前端调用公共js的方法给lua发送命令,lua接到命令,去执行一些方法,然后又通过回调返回到了前端,由于是第一次写这 ...

  5. lua学习项目笔记

    这几天草草的浏览了一下电子版的<lua程序设计>,没有懂的地方就自动忽略了,挑拣了一些可以理解的部分一直在推进.推进至后面的时候已经浑浑噩噩的了,有种想看完这本书的强迫症的感觉.推进CAP ...

  6. C++与Lua交互(一)

    引言 之前做手游项目时,客户端用lua做脚本,基本所有游戏逻辑都用它完成,玩起来有点不爽,感觉"太重"了.而我又比较偏服务端这边(仅有C++),所以热情不高.最近,加入了一个端游项 ...

  7. 我的2016年终总结(PF项目框架设计心得分享 2.0rc)

    在无数的日夜里,熬出了多少的黑眼圈,致勤勤恳恳工作的各位朋友与自己.每到了年末的时候总想写的什么,主要是为了回顾以往一年里到底做了什么,这便是年终总结的主要意义.在此我将要总结的是和我在技术层面上成长 ...

  8. lua 函数调用1 -- 闭包详解和C调用

    这里, 简单的记录一下lua中闭包的知识和C闭包调用 前提知识: 在lua api小记2中已经分析了lua中值的结构, 是一个 TValue{value, tt}组合, 如果有疑问, 可以去看一下 一 ...

  9. tolua++实现lua层调用c++技术分析

    tolua++技术分析 cocos2dx+lua 前言 一直都使用 cocos2dx + lua 进行游戏开发,用 Lua 开发可以专注于游戏逻辑的实现,另外一方面可以实现热更新:而且 lua 是一个 ...

随机推荐

  1. Android多线程分析之四:MessageQueue的实现

    Android多线程分析之四:MessageQueue的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前面两篇文章<Androi ...

  2. 关于基本类型值和引用类型值以及Vue官方API的array.$remove(reference)

    今天又是孟哥解惑. 数组里的元素也是指向内存地址么? 这个要分情况的. 无论a[0],a[2]在什么地方,只要其值是基本类型值,就是值的比较,只要其值是引用类型(对象),就是内存地址的比较. Vue官 ...

  3. MySQL 5.7新特性之Generated Column(函数索引)

    MySQL 5.7引入了Generated Column,这篇文章简单地介绍了Generated Column的使用方法和注意事项,为读者了解MySQL 5.7提供一个快速的.完整的教程.这篇文章围绕 ...

  4. Atitit. 类与对象的存储实现

    Atitit. 类与对象的存储实现 1. 类的结构和实现1 2. 类的方法属性都是hashtable存储的.2 3. Class的分类 常规类(T_CLASS), 抽象类(T_ABSTRACT T_C ...

  5. Atitit.eclipse 4.3 4.4  4.5 4.6新特性

    Atitit intellij idea的使用总结attilax 1. ideaIC-2016.2.4.exe1 1.1. Ij vs eclipse市场份额1 1.2. Ij的优点(方便的支持gro ...

  6. Apache多站点实现原理和配置

    Apache多站点实现原理 很多人常常看到一台服务器上跑多个站点,不同的域名访问不同的站点,就会有个疑惑:访问的时候并没有在地址栏中加入端口号,多个域名都是解析到这个服务器的IP地址,服务器怎么能够正 ...

  7. loadrunner协议选择

    协议选择参考: 应用类型 协议选择 web网站 http/HTML FTP服务器 FTP 邮件服务器 IMAP\POP3\SMTP CS:客户端以ADO,OLEDB方法连接后台数据库 MS SQLSe ...

  8. 快速入门系列--MySQL

    一直说要好好复习一下Mysql都木有时间,终于赶上最近新购买了阿里云,决定使用CentOS去试试.NET Core等相关的开发,于是决定好好的回顾下这部分知识,由于Mysql的数据库引擎是插件式的,对 ...

  9. ssh(sturts2_spring_hibernate) 框架搭建之spring

    一.spring总结: ⑴.spring是一个轻量级的JAVA开发框架,主要的作用是用来管理实例(可以解决JAVA类中new对象的问题,节省内存资源.)和降低代码之间的耦合性,促进代码模块化. ⑵.促 ...

  10. 前端工程师技能之photoshop巧用系列第五篇——雪碧图

    × 目录 [1]定义 [2]应用场景 [3]合并[4]实现[5]维护 前面的话 前面已经介绍过,描述性图片最终要合并为雪碧图.本文是photoshop巧用系列第五篇——雪碧图 定义 css雪碧图(sp ...