diff --git a/src/Instance.cxx b/src/Instance.cxx
index e0ae30dfe..a8ec8e3ae 100644
--- a/src/Instance.cxx
+++ b/src/Instance.cxx
@@ -70,6 +70,13 @@ Instance::~Instance() noexcept
 #endif
 }
 
+void
+Instance::OnStateModified() noexcept
+{
+	if (state_file)
+		state_file->CheckModified();
+}
+
 Partition *
 Instance::FindPartition(const char *name) noexcept
 {
diff --git a/src/Instance.hxx b/src/Instance.hxx
index 6d63efdaa..dec733630 100644
--- a/src/Instance.hxx
+++ b/src/Instance.hxx
@@ -152,6 +152,14 @@ struct Instance final
 		idle_monitor.OrMask(mask);
 	}
 
+	/**
+	 * Notify the #Instance that the state has been modified, and
+	 * the #StateFile may need to be saved.
+	 *
+	 * This method must be called from the main thread.
+	 */
+	void OnStateModified() noexcept;
+
 	/**
 	 * Find a #Partition with the given name.  Returns nullptr if
 	 * no such partition was found.
diff --git a/src/Main.cxx b/src/Main.cxx
index 5b3b5b740..d443d7bde 100644
--- a/src/Main.cxx
+++ b/src/Main.cxx
@@ -359,9 +359,8 @@ Instance::OnIdle(unsigned flags) noexcept
 	   clients */
 	client_list->IdleAdd(flags);
 
-	if (flags & (IDLE_PLAYLIST|IDLE_PLAYER|IDLE_MIXER|IDLE_OUTPUT) &&
-	    state_file != nullptr)
-		state_file->CheckModified();
+	if (flags & (IDLE_PLAYLIST|IDLE_PLAYER|IDLE_MIXER|IDLE_OUTPUT))
+		OnStateModified();
 }
 
 static inline void