diff --git a/include/libcamera/internal/thread.h b/include/libcamera/internal/thread.h
index 7b59e58..f6367a8 100644
--- a/include/libcamera/internal/thread.h
+++ b/include/libcamera/internal/thread.h
@@ -14,6 +14,7 @@
 
 #include <libcamera/signal.h>
 
+#include "libcamera/internal/message.h"
 #include "libcamera/internal/utils.h"
 
 namespace libcamera {
@@ -47,7 +48,7 @@ public:
 	EventDispatcher *eventDispatcher();
 	void setEventDispatcher(std::unique_ptr<EventDispatcher> dispatcher);
 
-	void dispatchMessages();
+	void dispatchMessages(Message::Type type = Message::Type::None);
 
 protected:
 	int exec();
diff --git a/src/libcamera/thread.cpp b/src/libcamera/thread.cpp
index d1750d7..87006a9 100644
--- a/src/libcamera/thread.cpp
+++ b/src/libcamera/thread.cpp
@@ -552,25 +552,42 @@ void Thread::removeMessages(Object *receiver)
 }
 
 /**
- * \brief Dispatch all posted messages for this thread
+ * \brief Dispatch posted messages for this thread
+ * \param[in] type The message type
+ *
+ * This function immediately dispatches all the messages previously posted for
+ * this thread with postMessage() that match the message \a type. If the \a type
+ * is Message::Type::None, all messages are dispatched.
  */
-void Thread::dispatchMessages()
+void Thread::dispatchMessages(Message::Type type)
 {
 	MutexLocker locker(data_->messages_.mutex_);
 
-	while (!data_->messages_.list_.empty()) {
-		std::unique_ptr<Message> msg = std::move(data_->messages_.list_.front());
-		data_->messages_.list_.pop_front();
-		if (!msg)
+	std::list<std::unique_ptr<Message>> &messages = data_->messages_.list_;
+
+	for (auto iter = messages.begin(); iter != messages.end(); ) {
+		std::unique_ptr<Message> &msg = *iter;
+
+		if (!msg) {
+			iter = data_->messages_.list_.erase(iter);
+			continue;
+		}
+
+		if (type != Message::Type::None && msg->type() != type) {
+			++iter;
 			continue;
+		}
 
-		Object *receiver = msg->receiver_;
-		ASSERT(data_ == receiver->thread()->data_);
+		std::unique_ptr<Message> message = std::move(msg);
+		iter = data_->messages_.list_.erase(iter);
 
+		Object *receiver = message->receiver_;
+		ASSERT(data_ == receiver->thread()->data_);
 		receiver->pendingMessages_--;
 
 		locker.unlock();
-		receiver->message(msg.get());
+		receiver->message(message.get());
+		message.reset();
 		locker.lock();
 	}
 }
