diff --git a/src/common/announce_multiplayer_room.h b/src/common/announce_multiplayer_room.h
index 091dded8f..f01e7cf74 100644
--- a/src/common/announce_multiplayer_room.h
+++ b/src/common/announce_multiplayer_room.h
@@ -60,15 +60,53 @@ using RoomList = std::vector<Room>;
 class Backend : NonCopyable {
 public:
     virtual ~Backend() = default;
+
+    /**
+     * Sets the Information that gets used for the announce
+     * @param uid The Id of the room
+     * @param name The name of the room
+     * @param port The port of the room
+     * @param net_version The version of the libNetwork that gets used
+     * @param has_password True if the room is passowrd protected
+     * @param preferred_game The preferred game of the room
+     * @param preferred_game_id The title id of the preferred game
+     */
     virtual void SetRoomInformation(const std::string& uid, const std::string& name, const u16 port,
                                     const u32 max_player, const u32 net_version,
                                     const bool has_password, const std::string& preferred_game,
                                     const u64 preferred_game_id) = 0;
+    /**
+     * Adds a player information to the data that gets announced
+     * @param nickname The nickname of the player
+     * @param mac_address The MAC Address of the player
+     * @param game_id The title id of the game the player plays
+     * @param game_name The name of the game the player plays
+     */
     virtual void AddPlayer(const std::string& nickname, const MacAddress& mac_address,
                            const u64 game_id, const std::string& game_name) = 0;
+
+    /**
+     * Send the data to the announce service
+     * @result The result of the announce attempt
+     */
     virtual std::future<Common::WebResult> Announce() = 0;
+
+    /**
+     * Empties the stored players
+     */
     virtual void ClearPlayers() = 0;
+
+    /**
+     * Get the room information from the announce service
+     * @param func a function that gets exectued when the get finished.
+     * Can be used as a callback
+     * @result A list of all rooms the announce service has
+     */
     virtual std::future<RoomList> GetRoomList(std::function<void()> func) = 0;
+
+    /**
+     * Sends a delete message to the announce service
+     */
     virtual void Delete() = 0;
 };
 
@@ -93,7 +131,7 @@ public:
     }
     void ClearPlayers() override {}
     std::future<RoomList> GetRoomList(std::function<void()> func) override {
-        return std::async(std::launch::async, [func]() {
+        return std::async(std::launch::deferred, [func]() {
             func();
             return RoomList{};
         });
diff --git a/src/core/announce_multiplayer_session.cpp b/src/core/announce_multiplayer_session.cpp
index a3ba78d78..af7d4fe58 100644
--- a/src/core/announce_multiplayer_session.cpp
+++ b/src/core/announce_multiplayer_session.cpp
@@ -19,7 +19,7 @@ namespace Core {
 // Time between room is announced to web_service
 static constexpr std::chrono::seconds announce_time_interval(15);
 
-AnnounceMultiplayerSession::AnnounceMultiplayerSession() : announce(false), finished(true) {
+AnnounceMultiplayerSession::AnnounceMultiplayerSession() : announce(false) {
 #ifdef ENABLE_WEB_SERVICE
     backend = std::make_unique<WebService::RoomJson>(
         Settings::values.announce_multiplayer_room_endpoint_url, Settings::values.citra_username,
@@ -39,19 +39,19 @@ void AnnounceMultiplayerSession::Start() {
 }
 
 void AnnounceMultiplayerSession::Stop() {
-    if (!announce && finished)
+    if (!announce)
         return;
     announce = false;
     // Detaching the loop, to not wait for the sleep to finish. The loop thread will finish soon.
     if (announce_multiplayer_thread) {
-        announce_multiplayer_thread->detach();
+        cv.notify_all();
+        announce_multiplayer_thread->join();
         announce_multiplayer_thread.reset();
         backend->Delete();
     }
 }
 
-std::shared_ptr<std::function<void(const Common::WebResult&)>>
-AnnounceMultiplayerSession::BindErrorCallback(
+AnnounceMultiplayerSession::CallbackHandle AnnounceMultiplayerSession::BindErrorCallback(
     std::function<void(const Common::WebResult&)> function) {
     std::lock_guard<std::mutex> lock(callback_mutex);
     auto handle = std::make_shared<std::function<void(const Common::WebResult&)>>(function);
@@ -59,8 +59,7 @@ AnnounceMultiplayerSession::BindErrorCallback(
     return handle;
 }
 
-void AnnounceMultiplayerSession::UnbindErrorCallback(
-    std::shared_ptr<std::function<void(const Common::WebResult&)>> handle) {
+void AnnounceMultiplayerSession::UnbindErrorCallback(CallbackHandle handle) {
     std::lock_guard<std::mutex> lock(callback_mutex);
     error_callbacks.erase(handle);
 }
@@ -70,13 +69,11 @@ AnnounceMultiplayerSession::~AnnounceMultiplayerSession() {
 }
 
 void AnnounceMultiplayerSession::AnnounceMultiplayerLoop() {
-    while (!finished) {
-        std::this_thread::sleep_for(announce_time_interval / 10);
-    }
     announce = true;
-    finished = false;
     std::future<Common::WebResult> future;
     while (announce) {
+        std::unique_lock<std::mutex> lock(cv_m);
+        cv.wait_for(lock, announce_time_interval);
         std::shared_ptr<Network::Room> room = Network::GetRoom().lock();
         if (!room) {
             announce = false;
@@ -107,9 +104,7 @@ void AnnounceMultiplayerSession::AnnounceMultiplayerLoop() {
                 }
             }
         }
-        std::this_thread::sleep_for(announce_time_interval);
     }
-    finished = true;
 }
 
 std::future<AnnounceMultiplayerRoom::RoomList> AnnounceMultiplayerSession::GetRoomList(
diff --git a/src/core/announce_multiplayer_session.h b/src/core/announce_multiplayer_session.h
index a7a36b82d..6faea3ae3 100644
--- a/src/core/announce_multiplayer_session.h
+++ b/src/core/announce_multiplayer_session.h
@@ -5,8 +5,10 @@
 #pragma once
 
 #include <atomic>
+#include <condition_variable>
 #include <functional>
 #include <memory>
+#include <mutex>
 #include <set>
 #include <thread>
 #include "common/announce_multiplayer_room.h"
@@ -21,6 +23,7 @@ namespace Core {
  */
 class AnnounceMultiplayerSession : NonCopyable {
 public:
+    using CallbackHandle = std::shared_ptr<std::function<void(const Common::WebResult&)>>;
     AnnounceMultiplayerSession();
     ~AnnounceMultiplayerSession();
 
@@ -29,14 +32,13 @@ public:
      * @param function The function that gets called
      * @return A handle that can be used the unbind the function
      */
-    std::shared_ptr<std::function<void(const Common::WebResult&)>> BindErrorCallback(
-        std::function<void(const Common::WebResult&)> function);
+    CallbackHandle BindErrorCallback(std::function<void(const Common::WebResult&)> function);
 
     /**
      * Unbind a function from the error callbacks
      * @param handle The handle for the function that should get unbind
      */
-    void UnbindErrorCallback(std::shared_ptr<std::function<void(const Common::WebResult&)>> handle);
+    void UnbindErrorCallback(CallbackHandle handle);
 
     /**
      * Starts the announce of a room to web services
@@ -57,13 +59,16 @@ public:
 
 private:
     std::atomic<bool> announce{false};
-    std::atomic<bool> finished{true};
+
+    /// conditional variable to notify the announce thread to end early
+    std::condition_variable cv;
+    std::mutex cv_m; ///< mutex for cv
     std::mutex callback_mutex;
-    std::set<std::shared_ptr<std::function<void(const Common::WebResult&)>>> error_callbacks;
+    std::set<CallbackHandle> error_callbacks;
     std::unique_ptr<std::thread> announce_multiplayer_thread;
 
-    std::unique_ptr<AnnounceMultiplayerRoom::Backend>
-        backend; ///< Backend interface that logs fields
+    /// Backend interface that logs fields
+    std::unique_ptr<AnnounceMultiplayerRoom::Backend> backend;
 
     void AnnounceMultiplayerLoop();
 };
diff --git a/src/web_service/web_backend.cpp b/src/web_service/web_backend.cpp
index 2b0f5a482..64f6a69bd 100644
--- a/src/web_service/web_backend.cpp
+++ b/src/web_service/web_backend.cpp
@@ -37,7 +37,7 @@ std::future<Common::WebResult> PostJson(const std::string& url, const std::strin
                                         const std::string& token) {
     if (url.empty()) {
         LOG_ERROR(WebService, "URL is invalid");
-        return std::async(std::launch::async, []() {
+        return std::async(std::launch::deferred, []() {
             return Common::WebResult{Common::WebResult::Code::InvalidURL, "URL is invalid"};
         });
     }
@@ -45,7 +45,7 @@ std::future<Common::WebResult> PostJson(const std::string& url, const std::strin
     const bool are_credentials_provided{!token.empty() && !username.empty()};
     if (!allow_anonymous && !are_credentials_provided) {
         LOG_ERROR(WebService, "Credentials must be provided for authenticated requests");
-        return std::async(std::launch::async, []() {
+        return std::async(std::launch::deferred, []() {
             return Common::WebResult{Common::WebResult::Code::CredentialsMissing,
                                      "Credentials needed"};
         });
@@ -97,13 +97,13 @@ std::future<T> GetJson(std::function<T(const std::string&)> func, const std::str
                        const std::string& token) {
     if (url.empty()) {
         LOG_ERROR(WebService, "URL is invalid");
-        return std::async(std::launch::async, [func{std::move(func)}]() { return func(""); });
+        return std::async(std::launch::deferred, [func{std::move(func)}]() { return func(""); });
     }
 
     const bool are_credentials_provided{!token.empty() && !username.empty()};
     if (!allow_anonymous && !are_credentials_provided) {
         LOG_ERROR(WebService, "Credentials must be provided for authenticated requests");
-        return std::async(std::launch::async, [func{std::move(func)}]() { return func(""); });
+        return std::async(std::launch::deferred, [func{std::move(func)}]() { return func(""); });
     }
 
     Win32WSAStartup();