我有这个函数调用数据库,我正在使用C和tcl / tk所以这个函数的tcl调用在C中执行,但是当发生这种情况时,tcl中的系统挂起它处理查询的时间调用以及它填充向量的时间,我希望tcl应用程序继续工作并将此进程放在一个单独的线程中。这就是我现在正在尝试的。
处理数据库调用并填充向量的C函数:
static int getEpochPrototype(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]){
Tcl_Obj *result;
char sampleid[15];
char tclxVec[15];
char tclyVec[15];
int length;
int numResults;
int i;
Blt_Vector *xCVec, *yCVec;
if (objc != 4) {
Tcl_WrongNumArgs(interp, 3, objv, "number of argument error");
return TCL_ERROR;
}
strcpy(sampleid,Tcl_GetStringFromObj(objv[1], &length));
strcpy(tclxVec,Tcl_GetStringFromObj(objv[2], &length));
strcpy(tclyVec,Tcl_GetStringFromObj(objv[3], &length));
if (Blt_VectorExists(interp, tclxVec) != TCL_OK || Blt_VectorExists(interp, tclyVec) != TCL_OK) {
if ((Blt_GetVector(interp, tclxVec, &xCVec) != TCL_OK) || (Blt_GetVector(interp, tclyVec, &yCVec) != TCL_OK)) {
return TCL_ERROR;
}
} else {
printf("Vector not found \n");
return TCL_ERROR;
}
char command[256];
PQclear(res);
strcpy(command, "select extract ('epoch' from \"Timestamp\"), \"BioAccumulated\" from \"Results\" where \"SampleID\" = '");
strcat(command, sampleid);
strcat(command, "' order by \"Timestamp\" asc");
res = PQexec(conn,command);
numResults = PQntuples(res);
double x[numResults], y[numResults];
for (i = 0; i < numResults; i++)
{
x[i] = strtod(PQgetvalue(res,i,0), NULL);
y[i] = strtod(PQgetvalue(res,i,1), NULL);
}
/* Put the data into BLT vectors */
if ((Blt_ResetVector(xCVec, x, numResults, numResults, TCL_VOLATILE) != TCL_OK) || (Blt_ResetVector(yCVec, y, numResults, numResults, TCL_VOLATILE) != TCL_OK)) {
return TCL_ERROR;
}
return TCL_OK;
}
TCL函数尝试将blt向量发送到c线程:
blt::vector create xVec
blt::vector create yVec
tsv::set graph xtemp_shared xVec
tsv::set graph yBio_shared yVec
thread::create {
load ./samples.so
connectDB2
#puts "[tsv::get details sampleid_shared]"
getEpochPrototype [tsv::get details sampleid_shared] [tsv::get graph xtemp_shared] [tsv::get graph yBio_shared]
}
当我尝试这个时,我得到了“找不到矢量”,这是我在找到矢量时出现的打印语句或者有错误,是否有其他方法可以做到或者我错过了什么?
答案 0 :(得分:0)
Tcl的threading model要求您从创建该解释器的线程访问Tcl解释器的任何特定实例。 (Tcl的实现广泛使用特定于线程的数据。)你可以从另一个线程填充那些C数组 - 那里通常的C并行规则 - 然后使用Tcl_ThreadQueueEvent
告诉另一个线程你有东西可以做;您发送的邮件实际上是代码+数据。
struct DoneReadingIntoArraysEvent {
Tcl_Event eventHeader;
Tcl_Interp *interp;
double *x, *y;
int length;
}
struct DoneReadingIntoArraysEvent callback;
callback.eventHeader.proc = &MyCallbackFunc;
callback.interp = theInterpHandleInTheOtherThread;
callback.x = x;
callback.y = y;
callback.length = numberOfValuesInArray;
Tcl_ThreadQueueEvent(mainThreadId, &callback.eventHeader, TCL_QUEUE_TAIL);
现在,在MyCallbackFunc
中,您将Tcl_Event*
参数转换回struct DoneReadingIntoArraysEvent
(安全;它是第一个成员!)并检索您需要告诉解释器的值(和有问题的翻译。)
为了将值实际存入Tcl,我强烈 考虑使用包含一大堆双Tcl_Obj
的列表Tcl_Obj
。这是一种在首次创建BLT时不可用的机制,它可能具有比您期望的更好的性能。
或者,如果值的数量很大并且您只需要传递它们和/或存储它们,请发送一大块二进制文件(binary scan
命令将能够在需要时选择位)。
相关API包括Tcl_NewListObj
,Tcl_NewDoubleObj
和Tcl_NewByteArrayObj
。