首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >TCL从TCL C线程和TCL脚本线程设置vwait变量

TCL从TCL C线程和TCL脚本线程设置vwait变量
EN

Stack Overflow用户
提问于 2017-11-30 09:59:59
回答 2查看 303关注 0票数 0

我的C++应用程序嵌入了TCL (8.6.7),同时需要通过Windows命名管道(dll)和TCP (TCP)获取数据。我想使用TCL线程来实现通过管道和套接字同时进行的数据采集。一个线程(threadPipe)通过TCL管理来自命名管道的数据读取,另一个线程通过TCL (threadTclSocket)管理套接字。通过TCL脚本的主线程( C++应用程序)启动数据采集,并在其TCL脚本中使用vwait forever等待(非阻塞)工作线程。

我的问题是:

  • 如何使TCL线程(threadPipe)和线程通过TCL (threadTclSocket)在完成时都设置主应用程序的变量:forever,以便主线程能够退出其事件循环?
  • 我读过关于Tcl_ThreadQueueEventTcl_ThreadAlert的文章,但我不明白如何使用它们在主线程中设置变量forever

如有任何建议,将不胜感激。

EN

回答 2

Stack Overflow用户

发布于 2017-11-30 12:36:14

您可能应该使用twapi命名的管道实现。我怀疑您的命名管道读取代码没有将其表示为支持tcl fileevent异步API的通道。如果您有这样的支持,就像在twapi版本中所发现的那样,那么您根本不需要额外的线程。您可以简单地使用fileevent,并在数据到达通道时调用一些tcl过程。

如果您坚持使用现有代码,则使用Tcl_ThreadQueueEvent将事件发送到tcl通知程序,以便解释器线程在处理该事件时调用函数。这将控制转移到解释器线程。下面是我以前写过的一个例子:

代码语言:javascript
运行
复制
static void MailslotSignalledProc(void *clientData)
{
    MailslotData *slotPtr = (MailslotData *)clientData;
    MailslotEvent *evPtr = NULL;
    DWORD cbRead, cbSize = 0, cQueued = 0;
    BOOL br = FALSE;

    Tcl_GetLongFromObj(NULL, slotPtr->sizeObj, &cbSize);
    GetOverlappedResult(slotPtr->handle, &slotPtr->ov, &cbRead,  FALSE);
    do
    {
        evPtr = (MailslotEvent *)ckalloc(sizeof(MailslotEvent));
        evPtr->header.proc = EventProc;
        evPtr->header.nextPtr = NULL;
        evPtr->interp = slotPtr->pkgPtr->interp;
        Tcl_Preserve(evPtr->interp);
        evPtr->slotPtr = slotPtr;
        evPtr->messageObj = Tcl_NewByteArrayObj(slotPtr->message, cbRead);
        Tcl_IncrRefCount(evPtr->messageObj);
        Tcl_ThreadQueueEvent(slotPtr->wait.tid, (Tcl_Event *)evPtr, TCL_QUEUE_TAIL);

        /*
         * Schedule another read on the mailslot. This may return
         * immediately if data is already available. We also rate-limit
         * by enforcing a wait after 64 immediate messages.
         */
        br = ReadFile(slotPtr->handle, slotPtr->message, cbSize, &cbRead, &slotPtr->ov);
        ++cQueued;
    } while (br && cQueued < 64);

    Tcl_ThreadAlert(slotPtr->wait.tid);
    return;
}

值得注意的是,我们有一个从Tcl_Event继承的结构,它允许我们在事件中放置自己的数据。我们可以发布一些事件,并在完成之后使用Tcl_ThreadAlert唤醒目标。目标函数(在本例中为EventProc)将传递此结构,但将在解释器线程上运行,因此我们必须考虑Tcl_Obj引用计数。

在您的情况下,听起来您可能只是希望在事件过程中设置永久变量。

如果有用的话,您可以看到全文件

但是,您确定不应该只在编写正确的命名管道通道上使用fileevent吗?

票数 2
EN

Stack Overflow用户

发布于 2017-12-01 08:50:52

谢谢你的建议,我已经解决了我的问题。

使用TCL脚本设置vwait forevervwait forever变量非常容易,只需要使用forever作为thread::send的结果,并让主TCL线程在其上等待。对于TCL线程,立即在forever中设置TCL_EventProc挂起主TCL解释器。为了解决这个问题,我将forever的设置推迟到事件循环空闲时,使用after,如下所示:

after idle {set forever thread}

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47570591

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档