diff --git a/meson.build b/meson.build
index c312f2c..0eca0a1 100644
--- a/meson.build
+++ b/meson.build
@@ -14,6 +14,7 @@ src_files = files([
 # libcamera install path camera.pc file ($prefix/lib/pkgconfig/camera.pc)
 libcamera_deps = [
       dependency('camera', required : true),
+      dependency('libevent_pthreads', required : true),
 ]
 
 cpp_arguments = [ '-Wno-unused-parameter', ]
diff --git a/simple-cam.cpp b/simple-cam.cpp
index 65e0f14..7fbb890 100644
--- a/simple-cam.cpp
+++ b/simple-cam.cpp
@@ -8,12 +8,57 @@
 #include <iomanip>
 #include <iostream>
 #include <memory>
+#include <mutex>
+
+#include <event2/event.h>
+#include <event2/thread.h>
 
 #include <libcamera/libcamera.h>
 
+#define TIMEOUT_SEC 3
+
 using namespace libcamera;
 std::shared_ptr<Camera> camera;
 
+/*
+ * --------------------------------------------------------------------
+ * Helper functions to interact and control the event loop.
+ */
+bool capture = true;
+std::mutex lock;
+std::list<std::function<void()>> calls_;
+struct event_base *event;
+
+void interrupt()
+{
+	event_base_loopbreak(event);
+}
+
+void callLater(const std::function<void()> &func)
+{
+	{
+		std::unique_lock<std::mutex> locker(lock);
+		calls_.push_back(func);
+	}
+
+	interrupt();
+}
+
+void dispatchCalls()
+{
+	std::unique_lock<std::mutex> locker(lock);
+
+	for (auto iter = calls_.begin(); iter != calls_.end(); ) {
+		std::function<void()> call = std::move(*iter);
+
+		iter = calls_.erase(iter);
+
+		locker.unlock();
+		call();
+		locker.lock();
+	}
+}
+
 /*
  * --------------------------------------------------------------------
  * Handle RequestComplete
@@ -21,13 +66,26 @@ std::shared_ptr<Camera> camera;
  * For each Camera::requestCompleted Signal emitted from the Camera the
  * connected Slot is invoked.
  *
+ * The Slot is invoked in the CameraManager's thread, hence one should avoid
+ * any heavy processing here. The processing of the request shall be re-directed
+ * to the application's thread instead, so as not to block the CameraManager's
+ * thread for large amount of time.
+ *
  * The Slot receives the Request as a parameter.
  */
+
+static void processRequest(Request *request);
+
 static void requestComplete(Request *request)
 {
 	if (request->status() == Request::RequestCancelled)
 		return;
 
+	callLater(std::bind(&processRequest, request));
+}
+
+static void processRequest(Request *request)
+{
 	const Request::BufferMap &buffers = request->buffers();
 
 	for (auto bufferPair : buffers) {
@@ -60,6 +118,15 @@ static void requestComplete(Request *request)
 	camera->queueRequest(request);
 }
 
+void timeoutTriggered(int fd, short event, void *arg)
+{
+	capture = false;
+	interrupt();
+
+	std::cout << "Capture ran for " << TIMEOUT_SEC << " seconds, Exiting."
+		  << std::endl;
+}
+
 int main()
 {
 	/*
@@ -321,18 +388,25 @@ int main()
 	 * In order to dispatch events received from the video devices, such
 	 * as buffer completions, an event loop has to be run.
 	 *
-	 * Libcamera provides its own default event dispatcher realized by
-	 * polling a set of file descriptors, but applications can integrate
-	 * their own even loop with the Libcamera EventDispatcher.
-	 *
-	 * Here, as an example, run the poll-based EventDispatcher for 3
-	 * seconds.
+	 * simple-cam uses a base event loop provided by libevent, which is run
+	 * for TIMEOUT_SEC seconds after which, the event loop is interrupted
+	 * via interrupt() and begins the cleanup. The interval for which the
+	 * event loop is being run, completed requests are processed via
+	 * requestComplete() handler.
 	 */
-	EventDispatcher *dispatcher = cm->eventDispatcher();
-	Timer timer;
-	timer.start(3000);
-	while (timer.isRunning())
-		dispatcher->processEvents();
+	struct event *ev;
+	struct timeval tv;
+
+	tv.tv_sec = TIMEOUT_SEC;
+	tv.tv_usec = 0;
+	evthread_use_pthreads();
+	event = event_base_new();
+	ev = event_new(event, -1, EV_TIMEOUT, &timeoutTriggered, NULL);
+	event_add(ev, &tv);
+	while (capture) {
+		dispatchCalls();
+		event_base_loop(event, EVLOOP_NO_EXIT_ON_EMPTY);
+	}
 
 	/*
 	 * --------------------------------------------------------------------
@@ -341,6 +415,10 @@ int main()
 	 * Stop the Camera, release resources and stop the CameraManager.
 	 * Libcamera has now released all resources it owned.
 	 */
+	event_free(ev);
+	event_base_free(event);
+	libevent_global_shutdown();
+
 	camera->stop();
 	allocator->free(stream);
 	delete allocator;
