Lua使用心得二

來源:互聯網
上載者:User

在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機制來防止指令碼的阻塞,這個方法下次再說了。。。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.