我的C++应用程序嵌入了TCL (8.6.7),同时需要通过Windows命名管道(dll)和TCP (TCP)获取数据。我想使用TCL线程来实现通过管道和套接字同时进行的数据采集。一个线程(threadPipe)通过TCL管理来自命名管道的数据读取,另一个线程通过TCL (threadTclSocket)管理套接字。通过TCL脚本的主线程( C++应用程序)启动数据采集,并在其TCL脚本中使用vwait forever等待(非阻塞)工作线程。
我的问题是:
forever,以便主线程能够退出其事件循环?Tcl_ThreadQueueEvent和Tcl_ThreadAlert的文章,但我不明白如何使用它们在主线程中设置变量forever。如有任何建议,将不胜感激。
发布于 2017-11-30 12:36:14
您可能应该使用twapi命名的管道实现。我怀疑您的命名管道读取代码没有将其表示为支持tcl fileevent异步API的通道。如果您有这样的支持,就像在twapi版本中所发现的那样,那么您根本不需要额外的线程。您可以简单地使用fileevent,并在数据到达通道时调用一些tcl过程。
如果您坚持使用现有代码,则使用Tcl_ThreadQueueEvent将事件发送到tcl通知程序,以便解释器线程在处理该事件时调用函数。这将控制转移到解释器线程。下面是我以前写过的一个例子:
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吗?
发布于 2017-12-01 08:50:52
谢谢你的建议,我已经解决了我的问题。
使用TCL脚本设置vwait forever的vwait forever变量非常容易,只需要使用forever作为thread::send的结果,并让主TCL线程在其上等待。对于TCL线程,立即在forever中设置TCL_EventProc挂起主TCL解释器。为了解决这个问题,我将forever的设置推迟到事件循环空闲时,使用after,如下所示:
after idle {set forever thread}
https://stackoverflow.com/questions/47570591
复制相似问题