【问题标题】:Using co_await to improve readability of my PPL code使用 co_await 来提高我的 PPL 代码的可读性
【发布时间】:2023-03-18 20:26:02
【问题描述】:

我正在使用 cpprestsdk 开发 CLIENT SERVER 应用程序,它运行良好。 现在我想使用协同程序提高我的代码的可读性(很多 .then() 方法)。 使用 co_await 编译器(在 VC++2015 或 VC++2017 上)将在“继续”中重构代码,摆脱 .then 语句。 我试图理解 co_await 是如何工作的,但实际上我并没有完全理解。 一般来说,如果我有这样的任务和延续:

client1.request(methods::GET, addr).then([=](http_response response)
{
    printf("Response status code %u returned.\n", response.status_code());

    if (response.status_code() == status_codes::OK)
    {
        wstring output = response.extract_utf16string().get();
        wcout << output << endl;
    }
 }).wait();

变得容易

auto response = co_await client1.request(methods::GET, addr); 
printf("Response status code %u returned.\n", response.status_code()); 
if (response.status_code() == status_codes::OK) 
{ wstring output = response.extract_utf16string().get();
  wcout << output << endl; 
} 

我现在的问题是当我有这样的情况时:

 pplx::task UploadFileToHttpServerAsync()
 {
      using concurrency::streams::file_stream;
      using concurrency::streams::basic_istream;

      namespace some_namespace = web::http;


      // Open stream to file.
      wstring filePath = L"out.txt";
      return file_stream<unsigned char>::open_istream(filePath).then([=](pplx::task<basic_istream<unsigned char>> previousTask)
      {
          try
          {
               auto fileStream = previousTask.get();

               // Make HTTP request with the file stream as the body.
               http_client client(XMLReader::data.URL);

               return client.request(methods::POST, filePath, fileStream).then([fileStream](pplx::task<http_response> previousTask)
                   {

如果我有 return 语句,如何使用 co_await 重构我的代码?

【问题讨论】:

  • 其余代码在哪里?
  • 我没有把该任务的整个代码,因为它对我的问题没用,但如果你愿意,我可以完全发布它

标签: visual-c++ async-await c++14 coroutine cpprest-sdk


【解决方案1】:

co_await 等背后的整个想法是您编写代码就好像它是同步的。

如果stream&lt;unsigned char&gt;::open_istream 是一个同步函数,它会返回什么?它将返回一个basic_istream&lt;unsigned char&gt;。这就是co_awaiting 将返回的内容(假设 co_await 机器存在于pplx::task):

wstring filePath = L"out.txt";
basic_istream<unsigned char> fileStream = co_await file_stream<unsigned char>::open_istream(filePath);

从那里开始,您继续编写代码,就好像它是同步的:

// Make HTTP request with the file stream as the body.
http_client client(XMLReader::data.URL);

然后,您执行co_await 的工作,继续编写您的代码,就好像它是完全同步的:

auto response = co_await client.request(methods::POST, filePath, fileStream);

然后您处理response,就像您可能在不完整的代码中一样。

以 return 语句开头的唯一原因是因为这就是您手动执行延续的方式。每一层延续都返回链中要继续的下一个任务,task::then 捕获task 并继续它。

使用co_await,您无需费心。你只是假装你正在编写同步代码,然后让编译器让它变得更快。

【讨论】:

  • static pplx::task<:basic_istream>> open_istream 是异步文件流。它在 cpprestsdk 的 filestream.h 中定义
  • @kenhero:我知道这一点。我的观点是co_await 使它出现同步。它解压返回的task 并从中提取值,从而允许您的其余代码正常处理该值。
  • 好的,我明白了,所以我必须像同步代码一样重写我的代码。
猜你喜欢
  • 1970-01-01
  • 2010-11-11
  • 2010-10-07
  • 2015-05-04
  • 1970-01-01
  • 2017-08-22
  • 1970-01-01
  • 2017-02-02
  • 2012-09-25
相关资源
最近更新 更多