我正在使用std::future
和boost::asio::async_connect
,以便在发生超时时取消操作,如下所示:https://stackoverflow.com/a/30428941
但是,std::future::wait_for()
会立即返回std::future_status::deferred
,即操作尚未开始。 conn_result.get()
之后会阻塞,直到因为远程主机没有收听而引发连接错误。我不想依赖它,因为它可能会持续很长时间,直到抛出套接字错误。
如何正确等待boost :: asio创建的期货?
编辑:SSCCE
#include <iostream>
#include <future>
#include <thread>
#include <boost/asio.hpp>
#include <boost/asio/use_future.hpp>
using boost::asio::ip::tcp;
int main(int argc, char* argv[]) {
boost::asio::io_service ioservice;
boost::asio::io_service::work work(ioservice);
std::thread t([&](){ioservice.run();});
tcp::resolver resolver(ioservice);
tcp::resolver::query query("127.0.0.1","27015"); // random unused adress
tcp::socket socket(ioservice);
std::future<tcp::resolver::iterator> conn_result = boost::asio::async_connect(socket,resolver.resolve(query),boost::asio::use_future);
std::cout << "IO Service running: " << (!ioservice.stopped() ? "y":"n") << std::endl;
auto status = conn_result.wait_for(std::chrono::milliseconds(500));
if (status == std::future_status::timeout) {
socket.cancel();
std::cout << "Timeout" << std::endl;
return 0;
} else if(status == std::future_status::deferred) {
std::cout << "Deferred" << std::endl;
}
// If the operation failed, then conn_result.get() will throw a
// boost::system::system_error.
try {
conn_result.get();
} catch(const boost::system::system_error& e) {
std::cerr << e.what() << std::endl;
}
ioservice.stop();
t.join();
return 0;
}
答案 0 :(得分:3)
这似乎是Stephan Lavavej回答here的错误。
我无法找到原始错误,但已将其修复为&#34; RTM版本&#34; (假设VS2013)。
这受内部错误编号DevDiv#255669&#34;的影响:
wait_for()
/wait_until()
请勿阻止&#34;。幸运的是,我收到了修复 来自我们的一个并发运行时开发人员Hong Hong。和我的 当前构建的VC11,这是有效的:使用我目前的VC11版本,这可行:
C:\Temp>type meow.cpp #include <stdio.h> #include <chrono> #include <future> #include <thread> #include <windows.h> using namespace std; long long counter() { LARGE_INTEGER li; QueryPerformanceCounter(&li); return li.QuadPart; } long long frequency() { LARGE_INTEGER li; QueryPerformanceFrequency(&li); return li.QuadPart; } int main() { printf("%02d.%02d.%05d.%02d\n", _MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 100000, _MSC_BUILD); future<int> f = async(launch::async, []() -> int { this_thread::sleep_for(chrono::milliseconds(250)); for (int i = 0; i < 5; ++i) { printf("Lambda: %d\n", i); this_thread::sleep_for(chrono::seconds(2)); } puts("Lambda: Returning."); return 1729; }); for (;;) { const auto fs = f.wait_for(chrono::seconds(0)); if (fs == future_status::deferred) { puts("Main thread: future_status::deferred (shouldn't happen, we used launch::async)"); } else if (fs == future_status::ready) { puts("Main thread: future_status::ready"); break; } else if (fs == future_status::timeout) { puts("Main thread: future_status::timeout"); } else { puts("Main thread: unknown future_status (UH OH)"); } this_thread::sleep_for(chrono::milliseconds(500)); } const long long start = counter(); const int n = f.get(); const long long finish = counter(); printf("Main thread: f.get() took %f microseconds to return %d.\n", (finish - start) * 1000000.0 / frequency(), n); } C:\Temp>cl /EHsc /nologo /W4 /MTd meow.cpp meow.cpp C:\Temp>meow 17.00.50419.00 Main thread: future_status::timeout Lambda: 0 Main thread: future_status::timeout Main thread: future_status::timeout Main thread: future_status::timeout Main thread: future_status::timeout Lambda: 1 Main thread: future_status::timeout Main thread: future_status::timeout Main thread: future_status::timeout Main thread: future_status::timeout Lambda: 2 Main thread: future_status::timeout Main thread: future_status::timeout Main thread: future_status::timeout Main thread: future_status::timeout Lambda: 3 Main thread: future_status::timeout Main thread: future_status::timeout Main thread: future_status::timeout Main thread: future_status::timeout Lambda: 4 Main thread: future_status::timeout Main thread: future_status::timeout Main thread: future_status::timeout Main thread: future_status::timeout Lambda: Returning. Main thread: future_status::ready Main thread: f.get() took 2.303971 microseconds to return 1729.
我插入了时间码来证明当wait_for()返回就绪时,f.get()会立即返回而不会阻塞。
基本上,解决方法是在报告延迟
时循环