diff --git a/aegisub/libaegisub/common/dispatch.cpp b/aegisub/libaegisub/common/dispatch.cpp
index fb04f6d491a1e2fa7a51fb472cf448601ed82686..a61a2fbad6b1b4f79c8c0ba8278cfb8c90492f49 100644
--- a/aegisub/libaegisub/common/dispatch.cpp
+++ b/aegisub/libaegisub/common/dispatch.cpp
@@ -18,6 +18,8 @@
 
 #include "libaegisub/dispatch.h"
 
+#include "libaegisub/util.h"
+
 #include <boost/asio/io_service.hpp>
 #include <boost/asio/strand.hpp>
 #include <condition_variable>
@@ -60,7 +62,10 @@ void Init(std::function<void (Thunk)> invoke_main) {
 	::invoke_main = invoke_main;
 
 	for (unsigned i = 0; i < std::max<unsigned>(1, std::thread::hardware_concurrency()); ++i)
-		std::thread([]{ ::service->run(); }).detach();
+		std::thread([]{
+			util::SetThreadName("Dispatch Worker");
+			::service->run();
+		}).detach();
 }
 
 void Queue::Async(Thunk thunk) {
diff --git a/aegisub/libaegisub/include/libaegisub/util.h b/aegisub/libaegisub/include/libaegisub/util.h
index ff71d9658dc99e64aa7180d3fa9038dbe99d6407..0a637c01f4ea9bc2e2bd8eba0f0d3fdcc8f2d8c0 100644
--- a/aegisub/libaegisub/include/libaegisub/util.h
+++ b/aegisub/libaegisub/include/libaegisub/util.h
@@ -55,5 +55,9 @@ namespace agi {
 		}
 	}
 
+	/// Set the name of the calling thread in the Visual Studio debugger
+	/// @param name New name for the thread
+	void SetThreadName(const char *name);
+
 	} // namespace util
 } // namespace agi
diff --git a/aegisub/libaegisub/unix/util.cpp b/aegisub/libaegisub/unix/util.cpp
index 7ccaafbad8b71b61425c0d6e0a438fe5a8a5489f..65c4a7c3a71dfca0e6d789bc4f2a8f50e5b65057 100644
--- a/aegisub/libaegisub/unix/util.cpp
+++ b/aegisub/libaegisub/unix/util.cpp
@@ -28,4 +28,6 @@ timeval time_log() {
 	return tv;
 }
 
+void SetThreadName(const char *) { }
+
 } }
diff --git a/aegisub/libaegisub/windows/util_win.cpp b/aegisub/libaegisub/windows/util_win.cpp
index 3abaacb245c899dc855575a77c7bb6acd2e5dd36..07283bd7f044a00a1fe97672599630a9571f3890 100644
--- a/aegisub/libaegisub/windows/util_win.cpp
+++ b/aegisub/libaegisub/windows/util_win.cpp
@@ -23,6 +23,9 @@
 
 #include "libaegisub/charset_conv_win.h"
 
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
 namespace agi {
 	namespace util {
 
@@ -74,5 +77,27 @@ agi_timeval time_log() {
 	return tv;
 }
 
+#define MS_VC_EXCEPTION 0x406d1388
+
+/// Parameters for setting the thread name
+struct THREADNAME_INFO {
+	DWORD dwType;     ///< must be 0x1000
+	LPCSTR szName;    ///< pointer to name (in same addr space)
+	DWORD dwThreadID; ///< thread ID (-1 caller thread)
+	DWORD dwFlags;    ///< reserved for future use, most be zero
+};
+
+void SetThreadName(LPCSTR szThreadName) {
+	THREADNAME_INFO info;
+	info.dwType = 0x1000;
+	info.szName = szThreadName;
+	info.dwThreadID = -1;
+	info.dwFlags = 0;
+	__try {
+		RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(DWORD), (ULONG_PTR *)&info);
+	}
+	__except (EXCEPTION_CONTINUE_EXECUTION) {}
+}
+
 	} // namespace io
 } // namespace agi
diff --git a/aegisub/src/main.cpp b/aegisub/src/main.cpp
index 537f6c47e296181476b0a1329e0d3eb8a2e76854..9715ce2f8faf7abca8dd9271fa1606da8bda80c6 100644
--- a/aegisub/src/main.cpp
+++ b/aegisub/src/main.cpp
@@ -90,37 +90,6 @@ static const char *LastStartupState = nullptr;
 #define StartupLog(a) LastStartupState = a
 #endif
 
-#ifdef __VISUALC__
-
-#define MS_VC_EXCEPTION 0x406d1388
-
-/// Parameters for setting the thread name
-struct THREADNAME_INFO {
-	DWORD dwType;     ///< must be 0x1000
-	LPCSTR szName;    ///< pointer to name (in same addr space)
-	DWORD dwThreadID; ///< thread ID (-1 caller thread)
-	DWORD dwFlags;    ///< reserved for future use, most be zero
-};
-
-/// Set the name of a thread in the visual studio debugger
-/// @param dwThreadID Thread ID, or -1 for caller
-/// @param szThreadName New name for the thread
-void SetThreadName(DWORD dwThreadID, LPCSTR szThreadName) {
-	THREADNAME_INFO info;
-	info.dwType = 0x1000;
-	info.szName = szThreadName;
-	info.dwThreadID = dwThreadID;
-	info.dwFlags = 0;
-	__try {
-		RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(DWORD), (ULONG_PTR *)&info);
-	}
-	__except (EXCEPTION_CONTINUE_EXECUTION) {}
-}
-#else
-void SetThreadName(int dwThreadID, const char *szThreadName) {
-}
-#endif
-
 void AegisubApp::OnAssertFailure(const wxChar *file, int line, const wxChar *func, const wxChar *cond, const wxChar *msg) {
 	LOG_A("wx/assert") << file << ":" << line << ":" << func << "() " << cond << ": " << msg;
 	wxApp::OnAssertFailure(file, line, func, cond, msg);
@@ -214,7 +183,7 @@ bool AegisubApp::OnInit() {
 	StartupLog("Load MRU");
 	config::mru = new agi::MRUManager(StandardPaths::DecodePath("?user/mru.json"), GET_DEFAULT_CONFIG(default_mru), config::opt);
 
-	SetThreadName(-1, "AegiMain");
+	agi::util::SetThreadName("AegiMain");
 
 	StartupLog("Inside OnInit");
 	frame = nullptr;
diff --git a/aegisub/src/utils.cpp b/aegisub/src/utils.cpp
index fbfefac47e6cff8ea48c6dfab6bd5d80875ea2c8..05e3b358dea995d7c24fda3cefb862602bbd5505 100644
--- a/aegisub/src/utils.cpp
+++ b/aegisub/src/utils.cpp
@@ -275,6 +275,7 @@ size_t MaxLineLength(std::string const& text) {
 	return std::max(max_line_length, current_line_length);
 }
 
+
 // OS X implementation in osx_utils.mm
 #ifndef __WXOSX_COCOA__
 void AddFullScreenButton(wxWindow *) { }