zoukankan      html  css  js  c++  java
  • (转)Lua使用心得二

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

    while 1 do

         do

    end

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

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

    总体思路:

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

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

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

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

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

  • 相关阅读:
    Evaluate Reverse Polish Notation
    openstack VM可以ping外部网络,但是外部网络ping不通VM
    Object Storage(Swift)安装过程——Havana
    完数c实现
    ubuntu用户及用户组文件信息
    Ubuntu12.04安装java以及Eclipse和Tomcat
    Ubuntu 12.04 Server OpenStack Havana多节点(OVS+GRE)安装
    ERROR:the server has either erred or is incapable of performing the requested operation
    openMPI小集群安装
    分片传输——send和recv函数
  • 原文地址:https://www.cnblogs.com/hummersofdie/p/2103123.html
Copyright © 2011-2022 走看看