带有 libev 和 pthread 的异步 hiredis,我做错了什么?
Asynchronous hiredis with libev and pthread, what am I doing wrong?
我正在为小型单色显示器编写 GUI,我想每秒更新一次屏幕上的数据。
数据存储在 redis 数据库中,我正在尝试使用 pthread、libev 和异步 hiredis 调用进行协调。
我的计划是让一个线程每秒从数据库中提取新数据并存储一个本地副本以便快速访问。
更新屏幕的另一个线程将随意访问该数据,而无需等待数据库访问。
第一个问题,我的做法对吗?
第二个问题,为什么我每秒都在轮询数据库?我想我可以切换到同步方法并让它工作,但这是正确的方法吗?
相关代码如下:
int main(int argc, char *argv[])
{
pthread_t dataThread;
pthread_t guiThread;
pthread_create(&dataThread, NULL, dataHandler, NULL);
pthread_create(&guiThread, NULL, guiHandler, NULL);
while (true)
{
sleep(10);
}
return 0;
}
在下文中,如果我在 redisAsync 命令后将 ev_loop(EV_DEFAULT_ 0);
移动到 while 循环内,我的回调会在第一个循环中被调用,但不会再被调用。就这样,我的回调永远不会被调用。
void* dataHandler(void *ptr)
{
m_ctx = redisAsyncConnect("127.0.0.1", 6379);
if (m_ctx->err) {
printf("Redis async connection failed. Error: %s\n", m_ctx->errstr);
exit(-1);
}
redisLibevAttach(EV_DEFAULT_ m_ctx);
redisAsyncSetConnectCallback(m_ctx,connectCallback);
redisAsyncSetDisconnectCallback(m_ctx,disconnectCallback);
ev_loop(EV_DEFAULT_ 0);
while (true)
{
int result;
result = redisAsyncCommand(m_ctx, updateCallback, (char*)"data1", "HGET data1 data");
printf("result: %d\n", result);
result = redisAsyncCommand(m_ctx, updateCallback, (char*)"data2", "HGET data2 data");
printf("result: %d\n", result);
//ev_loop(EV_DEFAULT_ 0); <- this will work one time
}
redisAsyncDisconnect(m_ctx);
return 0;
}
void updateCallback(redisAsyncContext *c, void *r, void *privdata)
{
redisReply *reply = (redisReply*)r;
if (reply == NULL) return;
printf("%s: %s\n", (char*)privdata, reply->str);
}
void* guiHandler(void *ptr)
{
while (true)
{
// Update the GUI accordingly
sleep(1);
}
}
首先,我建议您在使用 libev 之前阅读它的手册:
http://man7.org/linux/man-pages/man3/event.3.html
现在你的代码,
ev_loop 函数将启动一个事件循环,你只需要 "feed" 它有 2 个 HGET 操作。
为了添加更多操作,您需要为事件循环添加附加事件,但我不确定这是否适合您的情况。
如果您的线程的目的只是每 X 秒获取一次数据库,您为什么要使用异步方法? IMO 只使用 hiredis 同步 API
我正在为小型单色显示器编写 GUI,我想每秒更新一次屏幕上的数据。
数据存储在 redis 数据库中,我正在尝试使用 pthread、libev 和异步 hiredis 调用进行协调。
我的计划是让一个线程每秒从数据库中提取新数据并存储一个本地副本以便快速访问。
更新屏幕的另一个线程将随意访问该数据,而无需等待数据库访问。
第一个问题,我的做法对吗?
第二个问题,为什么我每秒都在轮询数据库?我想我可以切换到同步方法并让它工作,但这是正确的方法吗?
相关代码如下:
int main(int argc, char *argv[])
{
pthread_t dataThread;
pthread_t guiThread;
pthread_create(&dataThread, NULL, dataHandler, NULL);
pthread_create(&guiThread, NULL, guiHandler, NULL);
while (true)
{
sleep(10);
}
return 0;
}
在下文中,如果我在 redisAsync 命令后将 ev_loop(EV_DEFAULT_ 0);
移动到 while 循环内,我的回调会在第一个循环中被调用,但不会再被调用。就这样,我的回调永远不会被调用。
void* dataHandler(void *ptr)
{
m_ctx = redisAsyncConnect("127.0.0.1", 6379);
if (m_ctx->err) {
printf("Redis async connection failed. Error: %s\n", m_ctx->errstr);
exit(-1);
}
redisLibevAttach(EV_DEFAULT_ m_ctx);
redisAsyncSetConnectCallback(m_ctx,connectCallback);
redisAsyncSetDisconnectCallback(m_ctx,disconnectCallback);
ev_loop(EV_DEFAULT_ 0);
while (true)
{
int result;
result = redisAsyncCommand(m_ctx, updateCallback, (char*)"data1", "HGET data1 data");
printf("result: %d\n", result);
result = redisAsyncCommand(m_ctx, updateCallback, (char*)"data2", "HGET data2 data");
printf("result: %d\n", result);
//ev_loop(EV_DEFAULT_ 0); <- this will work one time
}
redisAsyncDisconnect(m_ctx);
return 0;
}
void updateCallback(redisAsyncContext *c, void *r, void *privdata)
{
redisReply *reply = (redisReply*)r;
if (reply == NULL) return;
printf("%s: %s\n", (char*)privdata, reply->str);
}
void* guiHandler(void *ptr)
{
while (true)
{
// Update the GUI accordingly
sleep(1);
}
}
首先,我建议您在使用 libev 之前阅读它的手册: http://man7.org/linux/man-pages/man3/event.3.html
现在你的代码, ev_loop 函数将启动一个事件循环,你只需要 "feed" 它有 2 个 HGET 操作。 为了添加更多操作,您需要为事件循环添加附加事件,但我不确定这是否适合您的情况。 如果您的线程的目的只是每 X 秒获取一次数据库,您为什么要使用异步方法? IMO 只使用 hiredis 同步 API