title: How to asynchronously read input from command line using boost asio in Windows?
body: <p>I found <a href="https://stackoverflow.com/questions/2831253/using-boostasioasync-read-with-stdin">this question</a> which asks how to read input asynchronously, but will only work with POSIX stream descriptors, which won't work on Windows. So, I found <a href="http://www.highscore.de/boost/process/process/tutorials.html#process.tutorials.async_io" rel="nofollow noreferrer">this tutorial</a> which shows that instead of using a POSIX stream descriptor I can use a <code>boost::asio::windows::stream_handle</code>.</p>
  
  <p>Following both examples I came up with the code below. When I run it, I cannot type anything into the command prompt, as the program immediately terminates. I'd like it to capture any input from the user, possibly into a <code>std::string</code>, while allowing other logic within my program to execute (i.e. perform asynchronous I/O from a Windows console).</p>
  
  <p>Essentially, I'm trying to avoid blocking my program when it attempts to read from <code>stdin</code>. I do not know if this is possible in Windows, as I also found <a href="http://comments.gmane.org/gmane.comp.lib.boost.asio.user/2394" rel="nofollow noreferrer">this post</a> which details problems another user encountered when trying to do the same thing.</p>
  
  <pre><code>#define _WIN32_WINNT 0x0501
  #define INPUT_BUFFER_LENGTH 512
  
  #include &lt;cstdio&gt;
  #include &lt;iostream&gt;
  
  #define BOOST_THREAD_USE_LIB // For MinGW 4.5 - (https://svn.boost.org/trac/boost/ticket/4878)
  #include &lt;boost/bind.hpp&gt;
  #include &lt;boost/asio.hpp&gt;
  
  class Example {
      public:
          Example( boost::asio::io_service&amp; io_service)
              : input_buffer( INPUT_BUFFER_LENGTH), input_handle( io_service)
          {
              // Read a line of input.
              boost::asio::async_read_until( input_handle, input_buffer, "\r\n",
                  boost::bind( &amp;Example::handle_read, this,
                      boost::asio::placeholders::error,
                      boost::asio::placeholders::bytes_transferred));
          }
          void handle_read( const boost::system::error_code&amp; error, std::size_t length);
          void handle_write( const boost::system::error_code&amp; error);
      private:
          boost::asio::streambuf input_buffer;
          boost::asio::windows::stream_handle input_handle;
  };
  
  void Example::handle_read( const boost::system::error_code&amp; error, std::size_t length)
  {
      if (!error)
      {
          // Remove newline from input.
          input_buffer.consume(1);
          input_buffer.commit( length - 1);
  
          std::istream is(&amp;input_buffer);
          std::string s;
          is &gt;&gt; s;
  
          std::cout &lt;&lt; s &lt;&lt; std::endl;
  
          boost::asio::async_read_until(input_handle, input_buffer, "\r\n",
             boost::bind( &amp;Example::handle_read, this,
                 boost::asio::placeholders::error,
                 boost::asio::placeholders::bytes_transferred));
      }
      else if( error == boost::asio::error::not_found)
      {
          std::cout &lt;&lt; "Did not receive ending character!" &lt;&lt; std::endl;
      }
  }
  
  void Example::handle_write( const boost::system::error_code&amp; error)
  {
      if (!error)
      {
          // Read a line of input.
          boost::asio::async_read_until(input_handle, input_buffer, "\r\n",
             boost::bind( &amp;Example::handle_read, this,
                 boost::asio::placeholders::error,
                 boost::asio::placeholders::bytes_transferred));
      }
  }
  
  int main( int argc, char ** argv)
  {
      try {
          boost::asio::io_service io_service;
          Example obj( io_service);
          io_service.run();
      } catch( std::exception &amp; e)
      {
          std::cout &lt;&lt; e.what() &lt;&lt; std::endl;
      }
      std::cout &lt;&lt; "Program has ended" &lt;&lt; std::endl;
      getchar();
      return 0;
  }
  </code></pre>