我有一些 asio 代码,用于从客户端传输文件。这段代码工作正常,如下:
bool FileTransferBehaviour::ConnectAndTransferFile(const std::string& _sender,
const std::string& _filePath,
size_t _numBytes)
{
// use a coroutine to accept the connection and receive the file.
bool result = false;
asio::co_spawn(m_ioContext,
[&result, &filePath, _numBytes, this]() mutable
-> asio::awaitable<void> {
auto maybeSock = co_await CoAwaitClientConnection();
if (maybeSock.has_value()) {
result = ReceiveFile(maybeSock.value(), filePath, _numBytes);
}
}, asio::detached);
m_ioContext.restart();
m_ioContext.run();
return result;
}
当前在内部 lambda 表达式中设置了
result
。我更愿意从协程返回这个结果,而不是通过引用捕获局部变量,即
bool FileTransferBehaviour::ConnectAndTransferFile(const std::string& _sender,
const std::string& _filePath,
size_t _numBytes)
{
// use a coroutine to accept the connection and receive the file.
bool result = co_await asio::co_spawn(m_ioContext,
&filePath, _numBytes, this]() mutable
-> asio::awaitable<bool> {
auto maybeSock = co_await CoAwaitClientConnection();
if (maybeSock.has_value()) {
co_return ReceiveFile(maybeSock.value(), filePath, _numBytes);
}
co_return false;
}, asio::detached);
m_ioContext.restart();
m_ioContext.run();
return result;
}
当我更改 lambda 的返回类型时,代码失败并显示
FileTransferBehaviour.cpp(101,42): error C2228: left of '.await_ready' must have
class/struct/union [MyProject,vcxproj]
FileTransferBehaviour.cpp(101,17): error C2440: 'initializing': cannot convert from
'void' to 'bool' [MyProject.vcxproj]
我正在使用 C++20 和 CL 版本 19.37.32824 (Visual Studio 2022)
使用 GCC 11.4.0 我收到以下错误:
FileTransferBehaviour.cpp:101:19: error: unable to find the promise type for this coroutine
101 | bool result = co_await asio::co_spawn(m_ioContext,
我错过了什么?
在您的第一个版本中,
ConnectAndTransferFile
不是协程。它是一个生成协程的函数,该协程恰好在函数内定义为 lambda。该协程被移交给 ASIO,并且您的外部非协程本质上会等待它完成然后再返回。
这是同步操作。
在您的第二个版本中,您已将
ConnectAndTransferFile
更改为协程。这就是您直接在 co_await asio::co_spawn(...)
中执行 ConnectAndTransferFile
时发生的情况。
当然,如果一个函数是协程,那么它就不能
return
;它必须co_return
它。此外,函数的签名现在需要指示要与该协程一起使用的 Promise 类型。这通常是使用返回值来完成的。就您而言,您可能希望它返回asio::awaitable<bool>
。
但这意味着调用协程的代码必须等待它来提取
bool
结果。您的协程可能也不应该 restart
和 run
上下文。