QThreadPool示例(QThreadPool example)
我正在寻找一些关于使用
QThreadPool
简洁示例。 这是我如何使用它:QThreadPool *thread_pool = QThreadPool::globalInstance(); MyThread *thread = new MyThread(); thread_pool->start(thread); class MyThread : public QRunnable { public: MyThread(); ~MyThread(); void run(); }; void MyThread::run() { qDebug() << "MyThread"; }
以上是正确的做法吗?
PS:我在参考文献中看到了waitForDone
,我什么时候应该调用waitForDone
?I'm looking for some concise example on the use of
QThreadPool
. Here's how I used it:QThreadPool *thread_pool = QThreadPool::globalInstance(); MyThread *thread = new MyThread(); thread_pool->start(thread); class MyThread : public QRunnable { public: MyThread(); ~MyThread(); void run(); }; void MyThread::run() { qDebug() << "MyThread"; }
Is the above the right practice ?
PS: I sawwaitForDone
in the reference, when should I callwaitForDone
?
原文:https://stackoverflow.com/questions/17235873
最满意答案
通过研究
libmpdclient
源代码,我想我可以自己回答。超时是库设计中不可恢复的错误。 这就是
mpd_recv_idle ()
的disable_timeout
参数首先出现的原因。期望同步空闲请求“永久”阻塞(直到MPD应答请求)。 这与我想要的不兼容,我可能不得不使用低级异步接口来实现我想要的。
这是我的解决方案(最小的错误检查)。
程序等待用户按ENTER键并在后台处理MPD空闲消息,该消息可以每200 ms中断一次。
少了什么东西:
- 返回代码解析
- 空闲消息响应解析
这是代码:
#include <string> #include <stdexcept> #include <memory> #include <iostream> #include <thread> #include <chrono> #include <netinet/in.h> #include <netdb.h> #include <strings.h> #include <unistd.h> #include <mpd/async.h> // #include <mpd/client.h> typedef std::unique_ptr<mpd_async, decltype(&mpd_async_free)> mpd_async_ptr; void check_error (const mpd_async_ptr &c, const std::string &s) { if (mpd_async_get_error (c.get ()) != MPD_ERROR_SUCCESS) { throw std::runtime_error (s); } } mpd_async_event async_poll (const mpd_async *async, timeval *tv) { int events = mpd_async_events (async); if (events == 0) { throw std::runtime_error ("mpd_async_events failed"); } int fd = mpd_async_get_fd (async); fd_set rfds, wfds, efds; FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); if (events & MPD_ASYNC_EVENT_READ) { FD_SET(fd, &rfds); } if (events & MPD_ASYNC_EVENT_WRITE) { FD_SET(fd, &wfds); } if (events & (MPD_ASYNC_EVENT_HUP|MPD_ASYNC_EVENT_ERROR)) { FD_SET(fd, &efds); } int ret = select (fd + 1, &rfds, &wfds, &efds, tv); if (ret > 0) { if (!FD_ISSET(fd, &rfds)) { events &= ~MPD_ASYNC_EVENT_READ; } if (!FD_ISSET(fd, &wfds)) { events &= ~MPD_ASYNC_EVENT_WRITE; } if (!FD_ISSET(fd, &efds)) { events &= ~(MPD_ASYNC_EVENT_HUP| MPD_ASYNC_EVENT_ERROR); } return (mpd_async_event) events; } return (mpd_async_event) 0; } int socket_connect (const std::string &host, uint16_t port) { int sockfd = socket (AF_INET, SOCK_STREAM, 0); hostent *server = gethostbyname (host.c_str ()); sockaddr_in server_addr; bzero ((char *) &server_addr, sizeof (server_addr)); server_addr.sin_family = AF_INET; bcopy ((char *) server->h_addr, (char *) &server_addr.sin_addr.s_addr, server->h_length); server_addr.sin_port = htons (port); if (::connect (sockfd, (struct sockaddr*) &server_addr, sizeof (server_addr)) < 0) { throw std::string ("ERROR connecting"); } return sockfd; } void mpd_notify_thread_proc (bool &app_is_running) { const std::string host = "127.0.0.1"; const uint16_t port = 7701; auto sockfd = socket_connect (host, port); mpd_async_ptr async_ptr {mpd_async_new (sockfd), mpd_async_free}; auto async = async_ptr.get (); if (async == nullptr) { throw std::runtime_error ("mpd_async_new failed"); } while (app_is_running) { timeval tv; tv.tv_sec = 0; tv.tv_usec = 200 * 1000; auto events = async_poll (async, &tv); if (events != 0) { if (!mpd_async_io (async, (mpd_async_event) events)) { throw std::runtime_error ("connection was closed"); } char* line_ptr; while ((line_ptr = mpd_async_recv_line (async)) != nullptr) { std::cout << "recv: " << line_ptr << "\n"; std::string line {line_ptr}; if (line.find ("OK") == 0) { if (!mpd_async_send_command (async, "idle", nullptr)) { throw std::runtime_error ("mpd_async_send_command failed"); } } } } } } int main(void) { bool app_is_running = true; std::thread mpd_notify_thread = std::thread ( [&] () { mpd_notify_thread_proc (app_is_running); }); std::string response; getline (std::cin, response); std::cout << "shutting down...\n"; app_is_running = false; mpd_notify_thread.join (); }
通过调用
select ()
而不使用timeval
并观察关闭pipe ()
,可以“尽可能快地”中断改进版本:#include <string> #include <stdexcept> #include <memory> #include <iostream> #include <thread> #include <chrono> #include <netinet/in.h> #include <netdb.h> #include <strings.h> #include <unistd.h> #include <mpd/async.h> // #include <mpd/client.h> typedef std::unique_ptr<mpd_async, decltype(&mpd_async_free)> mpd_async_ptr; void check_error (const mpd_async_ptr &c, const std::string &s) { if (mpd_async_get_error (c.get ()) != MPD_ERROR_SUCCESS) { throw std::runtime_error (s); } } mpd_async_event async_poll (const mpd_async *async, int *shutdown_fd) { int events = mpd_async_events (async); if (events == 0) { throw std::runtime_error ("mpd_async_events failed"); } int fd = mpd_async_get_fd (async); fd_set rfds, wfds, efds; FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); if (events & MPD_ASYNC_EVENT_READ) { FD_SET(fd, &rfds); } if (events & MPD_ASYNC_EVENT_WRITE) { FD_SET(fd, &wfds); } if (events & (MPD_ASYNC_EVENT_HUP|MPD_ASYNC_EVENT_ERROR)) { FD_SET(fd, &efds); } FD_SET(*shutdown_fd, &rfds); FD_SET(*shutdown_fd, &wfds); FD_SET(*shutdown_fd, &efds); int ret = select ((fd > *shutdown_fd ? fd : *shutdown_fd) + 1, &rfds, &wfds, &efds, NULL); if (ret > 0) { if (!FD_ISSET(fd, &rfds)) { events &= ~MPD_ASYNC_EVENT_READ; } if (!FD_ISSET(fd, &wfds)) { events &= ~MPD_ASYNC_EVENT_WRITE; } if (!FD_ISSET(fd, &efds)) { events &= ~(MPD_ASYNC_EVENT_HUP| MPD_ASYNC_EVENT_ERROR); } if (FD_ISSET(*shutdown_fd, &rfds)) { *shutdown_fd = 0; } if (FD_ISSET(*shutdown_fd, &wfds)) { *shutdown_fd = 0; } if (FD_ISSET(*shutdown_fd, &efds)) { *shutdown_fd = 0; } return (mpd_async_event) events; } return (mpd_async_event) 0; } int socket_connect (const std::string &host, uint16_t port) { int sockfd = socket (AF_INET, SOCK_STREAM, 0); hostent *server = gethostbyname (host.c_str ()); sockaddr_in server_addr; bzero ((char *) &server_addr, sizeof (server_addr)); server_addr.sin_family = AF_INET; bcopy ((char *) server->h_addr, (char *) &server_addr.sin_addr.s_addr, server->h_length); server_addr.sin_port = htons (port); if (::connect (sockfd, (struct sockaddr*) &server_addr, sizeof (server_addr)) < 0) { throw std::string ("ERROR connecting"); } return sockfd; } void mpd_notify_thread_proc (int shutdown_fd) { const std::string host = "127.0.0.1"; const uint16_t port = 7701; auto sockfd = socket_connect (host, port); mpd_async_ptr async_ptr {mpd_async_new (sockfd), mpd_async_free}; auto async = async_ptr.get (); if (async == nullptr) { throw std::runtime_error ("mpd_async_new failed"); } while (shutdown_fd != 0) { auto events = async_poll (async, &shutdown_fd); if (shutdown_fd == 0) { break; } if (events != 0) { if (!mpd_async_io (async, (mpd_async_event) events)) { throw std::runtime_error ("connection was closed"); } char* line_ptr; while ((line_ptr = mpd_async_recv_line (async)) != nullptr) { std::cout << "recv: " << line_ptr << "\n"; std::string line {line_ptr}; if (line.find ("OK") == 0) { if (!mpd_async_send_command (async, "idle", nullptr)) { throw std::runtime_error ("mpd_async_send_command failed"); } } } } } } int main(void) { int shutdown_pipe[2]; pipe (shutdown_pipe); std::thread mpd_notify_thread = std::thread ([&] () { mpd_notify_thread_proc (shutdown_pipe[0]); }); std::string response; getline (std::cin, response); std::cout << "shutting down...\n"; close (shutdown_pipe[1]); mpd_notify_thread.join (); close (shutdown_pipe[0]); }
如果您愿意以基于事件的样式编写代码(使用
libuv
和uvw
),那么这是一个更好的解决方案:#include <string> #include <stdexcept> #include <memory> #include <iostream> #include <uvw.hpp> int main(void) { auto loop = uvw::Loop::getDefault (); if (loop == nullptr) { throw std::runtime_error ("loop init failed"); } auto tcp = loop->resource<uvw::TcpHandle>(); if (tcp == nullptr) { throw std::runtime_error ("tcp init failed"); } tcp->once<uvw::ConnectEvent> ([] (const uvw::ConnectEvent &, uvw::TcpHandle &tcp) mutable { tcp.read (); }); tcp->once<uvw::ErrorEvent> ([] (const uvw::ErrorEvent &, uvw::TcpHandle &) mutable { std::cerr << "Connection error\n"; }); std::string buf; tcp->on<uvw::DataEvent> ([&] (const uvw::DataEvent &event, uvw::TcpHandle &tcp) mutable { std::string data {event.data.get (), event.length}; buf += data; std::string::size_type pos; while ((pos = buf.find ('\n')) != std::string::npos) { std::string line = buf.substr (0, pos); buf.erase (0, pos + 1); if (!line.compare (0, 2, "OK")) { const std::string idle = "idle\n"; std::unique_ptr<char[]> ptr {new char[idle.size ()]}; idle.copy (ptr.get (), idle.size ()); tcp.write (std::move (ptr), idle.size ()); } else { std::cout << line << "\n"; } } }); tcp->connect ("127.0.0.1", 7701); loop->run<uvw::Loop::Mode::DEFAULT> (); }
From studying the
libmpdclient
source code I think I can answer that myself.A timeout is an unrecoverable error in the library design. That's why the
disable_timeout
parameter formpd_recv_idle ()
is there in the first place.Synchronous idle requests are expected to block "forever" (until MPD answers the request). This is incompatible with what I want, I will probably have to use the low level async interface to achieve what I want.
And here is my solution (with minimal error checking).
The program waits for the user to press ENTER and processes MPD idle messages in the background which can be interrupted every 200 ms.
What's missing:
- return code parsing
- idle message response parsing
Here is the code:
#include <string> #include <stdexcept> #include <memory> #include <iostream> #include <thread> #include <chrono> #include <netinet/in.h> #include <netdb.h> #include <strings.h> #include <unistd.h> #include <mpd/async.h> // #include <mpd/client.h> typedef std::unique_ptr<mpd_async, decltype(&mpd_async_free)> mpd_async_ptr; void check_error (const mpd_async_ptr &c, const std::string &s) { if (mpd_async_get_error (c.get ()) != MPD_ERROR_SUCCESS) { throw std::runtime_error (s); } } mpd_async_event async_poll (const mpd_async *async, timeval *tv) { int events = mpd_async_events (async); if (events == 0) { throw std::runtime_error ("mpd_async_events failed"); } int fd = mpd_async_get_fd (async); fd_set rfds, wfds, efds; FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); if (events & MPD_ASYNC_EVENT_READ) { FD_SET(fd, &rfds); } if (events & MPD_ASYNC_EVENT_WRITE) { FD_SET(fd, &wfds); } if (events & (MPD_ASYNC_EVENT_HUP|MPD_ASYNC_EVENT_ERROR)) { FD_SET(fd, &efds); } int ret = select (fd + 1, &rfds, &wfds, &efds, tv); if (ret > 0) { if (!FD_ISSET(fd, &rfds)) { events &= ~MPD_ASYNC_EVENT_READ; } if (!FD_ISSET(fd, &wfds)) { events &= ~MPD_ASYNC_EVENT_WRITE; } if (!FD_ISSET(fd, &efds)) { events &= ~(MPD_ASYNC_EVENT_HUP| MPD_ASYNC_EVENT_ERROR); } return (mpd_async_event) events; } return (mpd_async_event) 0; } int socket_connect (const std::string &host, uint16_t port) { int sockfd = socket (AF_INET, SOCK_STREAM, 0); hostent *server = gethostbyname (host.c_str ()); sockaddr_in server_addr; bzero ((char *) &server_addr, sizeof (server_addr)); server_addr.sin_family = AF_INET; bcopy ((char *) server->h_addr, (char *) &server_addr.sin_addr.s_addr, server->h_length); server_addr.sin_port = htons (port); if (::connect (sockfd, (struct sockaddr*) &server_addr, sizeof (server_addr)) < 0) { throw std::string ("ERROR connecting"); } return sockfd; } void mpd_notify_thread_proc (bool &app_is_running) { const std::string host = "127.0.0.1"; const uint16_t port = 7701; auto sockfd = socket_connect (host, port); mpd_async_ptr async_ptr {mpd_async_new (sockfd), mpd_async_free}; auto async = async_ptr.get (); if (async == nullptr) { throw std::runtime_error ("mpd_async_new failed"); } while (app_is_running) { timeval tv; tv.tv_sec = 0; tv.tv_usec = 200 * 1000; auto events = async_poll (async, &tv); if (events != 0) { if (!mpd_async_io (async, (mpd_async_event) events)) { throw std::runtime_error ("connection was closed"); } char* line_ptr; while ((line_ptr = mpd_async_recv_line (async)) != nullptr) { std::cout << "recv: " << line_ptr << "\n"; std::string line {line_ptr}; if (line.find ("OK") == 0) { if (!mpd_async_send_command (async, "idle", nullptr)) { throw std::runtime_error ("mpd_async_send_command failed"); } } } } } } int main(void) { bool app_is_running = true; std::thread mpd_notify_thread = std::thread ( [&] () { mpd_notify_thread_proc (app_is_running); }); std::string response; getline (std::cin, response); std::cout << "shutting down...\n"; app_is_running = false; mpd_notify_thread.join (); }
An improved version can be interrupted "as fast as possible", by calling
select ()
without atimeval
and watching for a shutdownpipe ()
instead:#include <string> #include <stdexcept> #include <memory> #include <iostream> #include <thread> #include <chrono> #include <netinet/in.h> #include <netdb.h> #include <strings.h> #include <unistd.h> #include <mpd/async.h> // #include <mpd/client.h> typedef std::unique_ptr<mpd_async, decltype(&mpd_async_free)> mpd_async_ptr; void check_error (const mpd_async_ptr &c, const std::string &s) { if (mpd_async_get_error (c.get ()) != MPD_ERROR_SUCCESS) { throw std::runtime_error (s); } } mpd_async_event async_poll (const mpd_async *async, int *shutdown_fd) { int events = mpd_async_events (async); if (events == 0) { throw std::runtime_error ("mpd_async_events failed"); } int fd = mpd_async_get_fd (async); fd_set rfds, wfds, efds; FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); if (events & MPD_ASYNC_EVENT_READ) { FD_SET(fd, &rfds); } if (events & MPD_ASYNC_EVENT_WRITE) { FD_SET(fd, &wfds); } if (events & (MPD_ASYNC_EVENT_HUP|MPD_ASYNC_EVENT_ERROR)) { FD_SET(fd, &efds); } FD_SET(*shutdown_fd, &rfds); FD_SET(*shutdown_fd, &wfds); FD_SET(*shutdown_fd, &efds); int ret = select ((fd > *shutdown_fd ? fd : *shutdown_fd) + 1, &rfds, &wfds, &efds, NULL); if (ret > 0) { if (!FD_ISSET(fd, &rfds)) { events &= ~MPD_ASYNC_EVENT_READ; } if (!FD_ISSET(fd, &wfds)) { events &= ~MPD_ASYNC_EVENT_WRITE; } if (!FD_ISSET(fd, &efds)) { events &= ~(MPD_ASYNC_EVENT_HUP| MPD_ASYNC_EVENT_ERROR); } if (FD_ISSET(*shutdown_fd, &rfds)) { *shutdown_fd = 0; } if (FD_ISSET(*shutdown_fd, &wfds)) { *shutdown_fd = 0; } if (FD_ISSET(*shutdown_fd, &efds)) { *shutdown_fd = 0; } return (mpd_async_event) events; } return (mpd_async_event) 0; } int socket_connect (const std::string &host, uint16_t port) { int sockfd = socket (AF_INET, SOCK_STREAM, 0); hostent *server = gethostbyname (host.c_str ()); sockaddr_in server_addr; bzero ((char *) &server_addr, sizeof (server_addr)); server_addr.sin_family = AF_INET; bcopy ((char *) server->h_addr, (char *) &server_addr.sin_addr.s_addr, server->h_length); server_addr.sin_port = htons (port); if (::connect (sockfd, (struct sockaddr*) &server_addr, sizeof (server_addr)) < 0) { throw std::string ("ERROR connecting"); } return sockfd; } void mpd_notify_thread_proc (int shutdown_fd) { const std::string host = "127.0.0.1"; const uint16_t port = 7701; auto sockfd = socket_connect (host, port); mpd_async_ptr async_ptr {mpd_async_new (sockfd), mpd_async_free}; auto async = async_ptr.get (); if (async == nullptr) { throw std::runtime_error ("mpd_async_new failed"); } while (shutdown_fd != 0) { auto events = async_poll (async, &shutdown_fd); if (shutdown_fd == 0) { break; } if (events != 0) { if (!mpd_async_io (async, (mpd_async_event) events)) { throw std::runtime_error ("connection was closed"); } char* line_ptr; while ((line_ptr = mpd_async_recv_line (async)) != nullptr) { std::cout << "recv: " << line_ptr << "\n"; std::string line {line_ptr}; if (line.find ("OK") == 0) { if (!mpd_async_send_command (async, "idle", nullptr)) { throw std::runtime_error ("mpd_async_send_command failed"); } } } } } } int main(void) { int shutdown_pipe[2]; pipe (shutdown_pipe); std::thread mpd_notify_thread = std::thread ([&] () { mpd_notify_thread_proc (shutdown_pipe[0]); }); std::string response; getline (std::cin, response); std::cout << "shutting down...\n"; close (shutdown_pipe[1]); mpd_notify_thread.join (); close (shutdown_pipe[0]); }
An even better solution, if you're willing to write your code in an event based style (using
libuv
anduvw
):#include <string> #include <stdexcept> #include <memory> #include <iostream> #include <uvw.hpp> int main(void) { auto loop = uvw::Loop::getDefault (); if (loop == nullptr) { throw std::runtime_error ("loop init failed"); } auto tcp = loop->resource<uvw::TcpHandle>(); if (tcp == nullptr) { throw std::runtime_error ("tcp init failed"); } tcp->once<uvw::ConnectEvent> ([] (const uvw::ConnectEvent &, uvw::TcpHandle &tcp) mutable { tcp.read (); }); tcp->once<uvw::ErrorEvent> ([] (const uvw::ErrorEvent &, uvw::TcpHandle &) mutable { std::cerr << "Connection error\n"; }); std::string buf; tcp->on<uvw::DataEvent> ([&] (const uvw::DataEvent &event, uvw::TcpHandle &tcp) mutable { std::string data {event.data.get (), event.length}; buf += data; std::string::size_type pos; while ((pos = buf.find ('\n')) != std::string::npos) { std::string line = buf.substr (0, pos); buf.erase (0, pos + 1); if (!line.compare (0, 2, "OK")) { const std::string idle = "idle\n"; std::unique_ptr<char[]> ptr {new char[idle.size ()]}; idle.copy (ptr.get (), idle.size ()); tcp.write (std::move (ptr), idle.size ()); } else { std::cout << line << "\n"; } } }); tcp->connect ("127.0.0.1", 7701); loop->run<uvw::Loop::Mode::DEFAULT> (); }
相关问答
更多-
在断开连接的情况下,python-mpd2的代理重新连接(proxy for python-mpd2 to reconnect in case of disconnection)[2022-03-11]
在一些朋友的帮助下,stackoverflow和一些进一步阅读我可以解决这个问题。 这是代码 import mpd class MPDProxy: def __init__(self, host="localhost", port=6600, timeout=10): self.client = mpd.MPDClient() self.host = host self.port = port self.client.timeout ... -
使用sshfs时MPD权限被拒绝 - 如何更改权限?(MPD permission denied when using sshfs - how to change permissions?)[2023-10-12]
MPD可能未在您用于装入sshfs文件系统的同一用户帐户下运行。 请参阅FUSE FAQ和sshfs FAQ ,如果您对安全风险感到满意,请将user_allow_other选项和mount命令的-o allow_other选项添加。 MPD is probably not running under the same user account that you used to mount the sshfs filesystem. See the FUSE FAQ and the sshfs FAQ, t ... -
使用Hydra它是一个用于启动并行作业的过程管理系统。 Hydra旨在原生使用多种守护进程,如ssh,rsh,pbs,slurm和sge。 。 http://www.mpich.org/static/tarballs/3.0.2/hydra-3.0.2.tar.gz Use Hydra it is a process management system for starting parallel jobs. Hydra is designed to natively work with multiple ...
-
从String创建MPD文件(Create MPD file from String)[2022-04-02]
在播放DASH流时,您需要创建一个DashMediaSource.Factory。 第一个参数是DashChunkSource,它读取由清单定义的媒体文件。 第二个参数是读取清单的DataSource.Factory。 所以你需要提供一个DataSource.Factory来创建一个DataSource来读取你的清单。 请参阅下面代码片段中的manifestDataSourceFactory : DashMediaSource.Factory dashMediaSourceFactory = new Das ... -
无法找到mpd.conf文件(unable to find mpd.conf file)[2024-01-05]
此错误来自运行需要某些设置的旧版MPICH。 您可以尝试升级到http://www.mpich.org上提供的更新版本(最新版本为3.0.4),您不必担心设置MPD,因为它将使用更新的流程管理器(Hydra) ) 默认。 This error comes from running an old version of MPICH that requires some setup. You might try upgrading to a much newer version (the latest is 3. ... -
调试清单.mpd(Debug manifest .mpd)[2022-04-14]
大部分问题的原因都在错误消息中详细说明: This software does not handle incomplete presentations 。 您正在尝试验证实时流,并且此工具目前不具备该功能。 关于样本描述问题,它看起来像验证器不能识别avc3内容(即参数集在带内而不是在初始化段中)。 我会考虑这个错误,并建议你在https://github.com/Dash-Industry-Forum/Conformance-and-reference-source/issues提出问题。 The cau ... -
DASH MPD中的段数(Number of segments in a DASH MPD)[2022-02-02]
在这个例子中,你可以看到音频段的长度分别为9.98秒(duration = 9980,timescale = 1000)。 由于演示的持续时间为1分59.89秒,(持续时间=“PT0H1M59.89S”),即大约13个分段(最后一个较短)。 使用网址模板(/audio/hdworld_seg_audio$Number$.m4s)来检索每个片段(用您想要的片段编号替换$ Number $(第一个片段编号为1)。这同样适用于视频片段(除了它们是4.92每个秒,所以你会有25段) In this example, ... -
是的,可以用hydra替换MPD。 Hydra是MPICH已经使用了几年的发射器。 它可能不是API的直接交换,但是MPD的所有功能都应该存在,并且必须在启动之前设置守护进程等头痛。 Yes, it is possible to replace MPD with hydra. Hydra is the launcher that's been used by MPICH for a couple of years now. It probably won't be a straight swap in te ...
-
通过研究libmpdclient源代码,我想我可以自己回答。 超时是库设计中不可恢复的错误。 这就是mpd_recv_idle ()的disable_timeout参数首先出现的原因。 期望同步空闲请求“永久”阻塞(直到MPD应答请求)。 这与我想要的不兼容,我可能不得不使用低级异步接口来实现我想要的。 这是我的解决方案(最小的错误检查)。 程序等待用户按ENTER键并在后台处理MPD空闲消息,该消息可以每200 ms中断一次。 少了什么东西: 返回代码解析 空闲消息响应解析 这是代码: #include ...
-
经过更多搜索,我终于在musicpd论坛上发帖了 https://forum.musicpd.org/viewtopic.php?f=7&t=4034 而回应是: “MPD不记得最近加载的播放列表的名称,因此无法查询它。” After more searching, I finally posted on the musicpd forum https://forum.musicpd.org/viewtopic.php?f=7&t=4034 and the response was: "MPD does n ...