diff --git a/modules/gui/qt/medialibrary/mlfoldersmodel.cpp b/modules/gui/qt/medialibrary/mlfoldersmodel.cpp
index d54f72e9c677e23cb2db9bd755d6aa37a34c4461..7ffb8c296551ad5fb098093e6d7d14ec3d1ba4eb 100644
--- a/modules/gui/qt/medialibrary/mlfoldersmodel.cpp
+++ b/modules/gui/qt/medialibrary/mlfoldersmodel.cpp
@@ -19,6 +19,9 @@
 #include "mlfoldersmodel.hpp"
 #include <cassert>
 
+static const char* const ML_FOLDER_ADD_QUEUE = "ML_FOLDER_ADD_QUEUE";
+static const char* const ML_FOLDER_BAN_QUEUE = "ML_FOLDER_BAN_QUEUE";
+
 MLFoldersBaseModel::MLFoldersBaseModel( QObject *parent )
     : QAbstractListModel( parent )
     , m_ml_event_handle( nullptr , [this](vlc_ml_event_callback_t* cb ) {
@@ -102,13 +105,6 @@ void MLFoldersBaseModel::removeAt(int index)
 
 }
 
-void MLFoldersBaseModel::update()
-{
-    beginResetModel();
-    m_mrls = entryPoints();
-    endResetModel();
-}
-
 void MLFoldersBaseModel::onMlEvent( void* data , const vlc_ml_event_t* event )
 {
     auto self = static_cast<MLFoldersBaseModel *>( data );
@@ -120,21 +116,43 @@ void MLFoldersBaseModel::onMlEvent( void* data , const vlc_ml_event_t* event )
     }
 }
 
-std::vector<MLFoldersBaseModel::EntryPoint> MLFoldersModel::entryPoints() const
+void MLFoldersBaseModel::updateImpl(vlc_ml_folder_list_t* (*folderListFunc)( vlc_medialibrary_t* p_ml, const vlc_ml_query_params_t* params ))
 {
-    std::vector<MLFoldersBaseModel::EntryPoint> r;
+    if (m_updatePending)
+        return;
 
-    vlc_ml_folder_list_t* entrypoints = vlc_ml_list_entry_points( m_mediaLib->vlcMl(), nullptr );
-    if ( entrypoints != nullptr )
+    m_updatePending = true;
+    struct Ctx {
+        std::vector<MLFoldersBaseModel::EntryPoint> r;
+    };
+
+    m_mediaLib->runOnMLThread<Ctx>(this,
+    //ML thread
+    [folderListFunc](vlc_medialibrary_t* ml,  Ctx& ctx){
+        vlc_ml_folder_list_t* entrypoints = folderListFunc( ml, nullptr );
+        if ( entrypoints != nullptr )
+        {
+            for ( unsigned int i = 0; entrypoints && i < entrypoints->i_nb_items; i++ )
+                ctx.r.emplace_back( entrypoints->p_items[i] );
+            vlc_ml_release( entrypoints );
+        }
+    },
+    //UI thread
+    [this](quint64, Ctx& ctx)
     {
-        for ( unsigned int i = 0; entrypoints && i < entrypoints->i_nb_items; i++ )
-            r.emplace_back( entrypoints->p_items[i] );
-        vlc_ml_release( entrypoints );
-    }
+        beginResetModel();
+        m_mrls = std::move(ctx.r);
+        m_updatePending = false;
+        endResetModel();
+    });
+}
 
-    return r;
+void MLFoldersModel::update()
+{
+    updateImpl(vlc_ml_list_entry_points);
 }
 
+
 bool MLFoldersModel::failed(const vlc_ml_event_t *event) const
 {
     if ( event->i_type == VLC_ML_EVENT_ENTRY_POINT_ADDED && !event->entry_point_added.b_success )
@@ -153,37 +171,51 @@ bool MLFoldersModel::failed(const vlc_ml_event_t *event) const
 
 void MLFoldersModel::remove( const QUrl &mrl )
 {
-    vlc_ml_remove_folder( m_mediaLib->vlcMl() , qtu( mrl.toString( QUrl::FullyEncoded ) ) );
+    //UI data is updated on onMlEvent
+    m_mediaLib->runOnMLThread(this,
+    //ML thread
+    [mrl](vlc_medialibrary_t* ml){
+        vlc_ml_remove_folder( ml , qtu( mrl.toString( QUrl::FullyEncoded ) ) );
+    },
+    ML_FOLDER_ADD_QUEUE);
 }
 
 void MLFoldersModel::add(const QUrl &mrl )
 {
-    vlc_ml_add_folder( m_mediaLib->vlcMl() , qtu( mrl.toString( QUrl::FullyEncoded ) ) );
+    //UI data is updated on onMlEvent
+    m_mediaLib->runOnMLThread(this,
+    //ML thread
+    [mrl](vlc_medialibrary_t* ml){
+        vlc_ml_add_folder( ml, qtu( mrl.toString( QUrl::FullyEncoded ) ) );
+    },
+    ML_FOLDER_ADD_QUEUE);
 }
 
 void MLBannedFoldersModel::remove(const QUrl &mrl)
 {
-    vlc_ml_unban_folder( m_mediaLib->vlcMl() , qtu( mrl.toString( QUrl::FullyEncoded ) ) );
+    //UI data is updated on onMlEvent
+    m_mediaLib->runOnMLThread(this,
+    //ML thread
+    [mrl](vlc_medialibrary_t* ml){
+        vlc_ml_unban_folder( ml , qtu( mrl.toString( QUrl::FullyEncoded ) ) );
+    },
+    ML_FOLDER_BAN_QUEUE);
 }
 
 void MLBannedFoldersModel::add(const QUrl &mrl)
 {
-    vlc_ml_ban_folder( m_mediaLib->vlcMl() , qtu( mrl.toString( QUrl::FullyEncoded ) ) );
+    //UI data is updated on onMlEvent
+    m_mediaLib->runOnMLThread(this,
+    //ML thread
+    [mrl](vlc_medialibrary_t* ml){
+        vlc_ml_ban_folder( ml , qtu( mrl.toString( QUrl::FullyEncoded ) ) );
+    },
+    ML_FOLDER_BAN_QUEUE);
 }
 
-std::vector<MLFoldersBaseModel::EntryPoint> MLBannedFoldersModel::entryPoints() const
+void MLBannedFoldersModel::update()
 {
-    std::vector<MLFoldersBaseModel::EntryPoint> r;
-
-    vlc_ml_folder_list_t* entrypoints = vlc_ml_list_banned_entry_points( m_mediaLib->vlcMl(), nullptr );
-    if ( entrypoints != nullptr )
-    {
-        for ( unsigned int i = 0; entrypoints && i < entrypoints->i_nb_items; i++ )
-            r.emplace_back( entrypoints->p_items[i] );
-        vlc_ml_release( entrypoints );
-    }
-
-    return r;
+    updateImpl(vlc_ml_list_banned_entry_points);
 }
 
 bool MLBannedFoldersModel::failed(const vlc_ml_event_t *event) const
diff --git a/modules/gui/qt/medialibrary/mlfoldersmodel.hpp b/modules/gui/qt/medialibrary/mlfoldersmodel.hpp
index 23743562faeebe7d95a168f66800a427ad4ca556..5f47e632423a914df4e96baed473febe235cca42 100644
--- a/modules/gui/qt/medialibrary/mlfoldersmodel.hpp
+++ b/modules/gui/qt/medialibrary/mlfoldersmodel.hpp
@@ -82,12 +82,12 @@ protected:
         bool banned;
     };
 
-    virtual std::vector<EntryPoint> entryPoints() const = 0;
     virtual bool failed( const vlc_ml_event_t* event ) const = 0; // will be called outside the main thread
 
 protected:
     static void onMlEvent( void* data , const vlc_ml_event_t* event );
-    void update();
+    virtual void update() = 0;
+    void updateImpl(vlc_ml_folder_list_t* (*folderListFunc)( vlc_medialibrary_t* p_ml, const vlc_ml_query_params_t* params));
 
     using EventCallbackPtr = std::unique_ptr<vlc_ml_event_callback_t, std::function<void( vlc_ml_event_callback_t* )>>;
 
@@ -95,6 +95,7 @@ protected:
     MediaLib *m_mediaLib = nullptr;
     MainCtx* m_ctx = nullptr;
     EventCallbackPtr m_ml_event_handle;
+    bool m_updatePending = false;
 };
 
 class MLFoldersModel : public MLFoldersBaseModel
@@ -106,7 +107,7 @@ public:
     void add( const QUrl &mrl ) override;
 
 private:
-    std::vector<EntryPoint> entryPoints() const final;
+    void update() override final;
     bool failed( const vlc_ml_event_t* event ) const override;
 };
 
@@ -119,7 +120,7 @@ public:
     void add( const QUrl &mrl ) override;
 
 private:
-    std::vector<EntryPoint> entryPoints() const final;
+    void update() override final;
     bool failed( const vlc_ml_event_t* event ) const override;
 };