来自Lua脚本的nanosleep()调用暂停了QT GUI线程

yon*_*zhy 7 c c++ lua qt4

我正在开发一种测试工具,用于从PC并行端口生成波形.该工具的目的是产生波形的任何模式与定时毫秒的准确性,所以我使用的Lua脚本来定义波形模式,GUI启动新的QThread运行脚本时用户点击[开始]按钮.

Lua的以下三个函数被实现为C++全局函数:

  • pwrite:将数据写入并行端口.
  • msleep:等待某个ms(使用nanosleep()实现)
  • print:覆盖Lua默认打印功能,此功能会将消息附加到一个QTextEdit小部件.

当调用pwrite时,写入的数据存储在全局变量中,然后以20ms的间隔更新GUI以更新GUI上的并行端口数据.(这20毫秒刷新间隔是不是一个很好的设计,但我还没有搞清楚如何使用信号进行GUI更新,当数据发生变化).

该工具现在基本上是功能性的.波形输出没有问题,但并行端口数据更新有一些问题:

当Lua调用msleep时,GUI线程停止,并行端口数据仅在msleep结束后更新.

所以我的问题是:

  1. 如何实现sleep方法,以便它不会阻止GUI线程更新?

  2. 如何实现pwrite,以便GUI在写入数据发生变化时可以接收信号来更新并行端口数据?

程序GUI如下链接: 程序GUI

相关代码:

    /* common.cpp file */

int L_MSleep(lua_State* l)
{
    int milisec=0;
    struct timespec req={0, 0};
    time_t sec;

    milisec=luaL_optint(l,1,0); // obtain parameter

    if (milisec==0)
       return 0;

    sec=(int)(milisec/1000);

    milisec=milisec-(sec*1000);
    req.tv_sec=sec;
    req.tv_nsec=milisec*1000000L;

    while(nanosleep(&req,&req)==-1)
         continue;

    return 1;
}


/* LuaRunner.cpp file */
LuaRunner::LuaRunner(QObject *parent) :
    QThread(parent)
{
    runlua = false;
}

void LuaRunner::run()
{
    QString err = "";

    runlua = true;
    LUA_RunScript(this->ff, err);
    runlua = false;

    if(err != "")
    {
        emit errorMessage(err);
    }
}

int LuaRunner::LUA_RunScript(QString ff, QString &err)
{
    L = lua_open();
    luaL_openlibs(L);

    if (luaL_loadfile(L, ff.toAscii()) || lua_pcall(L, 0, 0, 0))
    {
        err = QString(lua_tostring(L, -1));
        return -1;
    }

    lua_register(L, "ssleep", L_SSleep);
    lua_register(L, "msleep", L_MSleep);
    lua_register(L, "pwrite", L_PortWrite);
    lua_register(L, "print", L_Log);

    lua_getglobal(L, "dotest");
    if (!lua_isfunction(L, -1))
    {
        err = QString("Test function(dotest) should be a function");
        return -1;
    }

    if(lua_pcall(L, 0, 0, 0))
    {
        err = QString(lua_tostring(L, -1));
        return -1;
    }

    lua_close(L);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Dou*_*rie 0

也许你应该使用QT的msleep,因为它是供使用的QThread