There is no need to call PostQueuedCompletionStatus to stop the io_service if the outstanding work count is initially zero. A run/poll call can only be calling GetQueuedCompletionStatus if it the count was non-zero at some point. However, if it was previously non-zero, then the io_service will have already been stop()-ed when the count was decremented to zero.
diff --git a/asio/include/asio/detail/impl/win_iocp_io_service.ipp b/asio/include/asio/detail/impl/win_iocp_io_service.ipp index 030f5a8..2580ee2 100644 --- a/asio/include/asio/detail/impl/win_iocp_io_service.ipp +++ b/asio/include/asio/detail/impl/win_iocp_io_service.ipp
@@ -147,7 +147,7 @@ { if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0) { - stop(); + InterlockedExchange(&stopped_, 1); ec = asio::error_code(); return 0; } @@ -165,7 +165,7 @@ { if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0) { - stop(); + InterlockedExchange(&stopped_, 1); ec = asio::error_code(); return 0; } @@ -179,7 +179,7 @@ { if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0) { - stop(); + InterlockedExchange(&stopped_, 1); ec = asio::error_code(); return 0; } @@ -197,7 +197,7 @@ { if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0) { - stop(); + InterlockedExchange(&stopped_, 1); ec = asio::error_code(); return 0; }