diff --git a/mythtv/programs/mythfrontend/guidegrid.cpp b/mythtv/programs/mythfrontend/guidegrid.cpp
index 5a5f52c..142d810 100644
--- a/mythtv/programs/mythfrontend/guidegrid.cpp
+++ b/mythtv/programs/mythfrontend/guidegrid.cpp
@@ -164,6 +164,206 @@ bool JumpToChannel::Update(void)
     }
 }
 
+class GuideStatus
+{
+public:
+    unsigned int m_firstRow;
+    int m_numRows;
+    QVector<int> m_channums;
+    uint m_currentStartChannel;
+    QDateTime m_currentStartTime;
+    QDateTime m_currentEndTime;
+    int m_currentRow;
+    int m_currentCol;
+    int m_channelCount;
+    int m_timeCount;
+    bool m_verticalLayout;
+    QDateTime m_firstTime;
+    QDateTime m_lastTime;
+    int m_channelInfos_size;
+    MythRect m_gg_programRect;
+    int m_gg_channelCount;
+};
+
+class GuideUpdateClosure
+{
+public:
+    GuideUpdateClosure(GuideGrid *guide) : m_guide(guide), m_seq(++s_seq) {}
+
+    // Execute the initial non-UI part (in a separate thread).  Return
+    // true if ExecuteUI() should be run later, or false if the work
+    // is no longer relevant (e.g., the UI elements have scrolled
+    // offscreen by now).
+    virtual bool ExecuteNonUI(void) = 0;
+    // Execute the UI part in the UI thread.
+    virtual void ExecuteUI(void) = 0;
+
+protected:
+    GuideGrid *m_guide;
+    unsigned m_seq;
+    static unsigned s_seq;
+};
+unsigned GuideUpdateClosure::s_seq;
+
+struct UIGuideElement {
+    UIGuideElement(int row, int col, const QRect &area,
+                   const QString &title, const QString &category,
+                   int arrow, int recType, int recStat, bool selected)
+        : m_row(row), m_col(col), m_area(area), m_title(title),
+          m_category(category), m_arrow(arrow), m_recType(recType),
+          m_recStat(recStat), m_selected(selected) {}
+    UIGuideElement(void) {}
+    int m_row;
+    int m_col;
+    QRect m_area;
+    QString m_title;
+    QString m_category;
+    int m_arrow;
+    int m_recType;
+    int m_recStat;
+    bool m_selected;
+};
+
+class GuideUpdateProgramRow : public GuideUpdateClosure
+{
+public:
+    GuideUpdateProgramRow(GuideGrid *guide, GuideStatus gs,
+                          const QVector<ProgramList*> &proglists
+                          )
+        : GuideUpdateClosure(guide),
+          m_gs(gs),
+          m_proglists(proglists)
+    {
+        for (int i = m_gs.m_firstRow; i < m_gs.m_firstRow + m_gs.m_numRows; ++i)
+            for (int j = 0; j < MAX_DISPLAY_TIMES; ++j)
+                m_programInfos[i][j] = NULL;
+    }
+    virtual bool ExecuteNonUI(void)
+    {
+        // Don't bother to do any work if the starting coordinates of
+        // the guide have changed while the thread was waiting to
+        // start.
+        if (m_gs.m_currentStartChannel != m_guide->GetCurrentStartChannel() ||
+            m_gs.m_currentStartTime != m_guide->GetCurrentStartTime())
+        {
+            return false;
+        }
+
+        for (int i = 0; i < m_gs.m_numRows; ++i)
+        {
+            int row = i + m_gs.m_firstRow;
+            if (!m_proglists[i])
+                m_proglists[i] =
+                    m_guide->getProgramListFromProgram(m_gs.m_channums[i]);
+            fillProgramRowInfosWith(row, m_gs.m_channums[i], m_gs.m_currentStartTime,
+                                    m_proglists[i]);
+        }
+        //sleep(1);
+        return true;
+    }
+    virtual void ExecuteUI(void)
+    {
+        m_guide->updateProgramsUI(m_gs.m_firstRow, m_gs.m_numRows,
+                                  m_progPast, m_proglists, m_result);
+    }
+    void fillProgramRowInfosWith(int row, int chanNum, QDateTime start,
+                                 ProgramList *proglist);
+    const GuideStatus m_gs;
+    QVector<ProgramList*> m_proglists;
+    ProgramInfo *m_programInfos[MAX_DISPLAY_CHANS][MAX_DISPLAY_TIMES];
+    int m_progPast;
+    QVector<UIGuideElement> m_result;
+};
+
+class GuideUpdateChannels : public GuideUpdateClosure
+{
+public:
+    GuideUpdateChannels(GuideGrid *guide, uint startChan)
+        : GuideUpdateClosure(guide), m_currentStartChannel(startChan) {}
+    virtual bool ExecuteNonUI(void)
+    {
+        if (m_currentStartChannel != m_guide->GetCurrentStartChannel())
+            return false;
+        m_guide->updateChannelsNonUI(m_chinfos, m_unavailables);
+        return true;
+    }
+    virtual void ExecuteUI(void)
+    {
+        m_guide->updateChannelsUI(m_chinfos, m_unavailables);
+    }
+    uint m_currentStartChannel;
+    QVector<ChannelInfo *> m_chinfos;
+    QVector<bool> m_unavailables;
+};
+
+class UpdateGuideEvent : public QEvent
+{
+public:
+    UpdateGuideEvent(GuideUpdateClosure *closure) :
+        QEvent(kEventType), m_closure(closure) {}
+    GuideUpdateClosure *m_closure;
+    static Type kEventType;
+};
+QEvent::Type UpdateGuideEvent::kEventType =
+    (QEvent::Type) QEvent::registerEventType();
+
+class GuideHelper : public QRunnable
+{
+public:
+    GuideHelper(GuideGrid *guide, GuideUpdateClosure *closure)
+        : m_guide(guide), m_closure(closure)
+    {
+        QMutexLocker locker(&s_lock);
+        ++s_loading[m_guide];
+    }
+    virtual void run(void)
+    {
+        QThread::currentThread()->setPriority(QThread::IdlePriority);
+        if (m_closure)
+        {
+            if (m_closure->ExecuteNonUI())
+                QCoreApplication::postEvent(m_guide,
+                                            new UpdateGuideEvent(m_closure));
+            else
+            {
+                delete m_closure;
+                m_closure = NULL;
+            }
+        }
+
+        QMutexLocker locker(&s_lock);
+        --s_loading[m_guide];
+        if (!s_loading[m_guide])
+            s_wait.wakeAll();
+    }
+    static bool IsLoading(GuideGrid *guide)
+    {
+        QMutexLocker locker(&s_lock);
+        return s_loading[guide];
+    }
+    static void Wait(GuideGrid *guide)
+    {
+        QMutexLocker locker(&s_lock);
+        if (!s_loading[guide])
+            return;
+        while (s_wait.wait(&s_lock))
+        {
+            if (!s_loading[guide])
+                return;
+        }
+    }
+private:
+    GuideGrid *m_guide;
+    GuideUpdateClosure *m_closure;
+
+    static QMutex                s_lock;
+    static QWaitCondition        s_wait;
+    static QMap<GuideGrid*,uint> s_loading;
+};
+QMutex                GuideHelper::s_lock;
+QWaitCondition        GuideHelper::s_wait;
+QMap<GuideGrid*,uint> GuideHelper::s_loading;
+
 void GuideGrid::RunProgramGuide(uint chanid, const QString &channum,
                                 const QDateTime startTime,
                                 TV *player, bool embedVideo,
@@ -241,6 +441,7 @@ GuideGrid::GuideGrid(MythScreenStack *parent,
            m_previewVideoRefreshTimer(new QTimer(this)),
            m_channelOrdering(gCoreContext->GetSetting("ChannelOrdering", "channum")),
            m_updateTimer(NULL),
+           m_threadPool("GuideGridHelperPool"),
            m_changrpid(changrpid),
            m_changrplist(ChannelGroup::GetChannelGroups(false)),
            m_jumpToChannelLock(QMutex::Recursive),
@@ -274,6 +475,7 @@ GuideGrid::GuideGrid(MythScreenStack *parent,
     int secsoffset = -((m_originalStartTime.time().minute() % 30) * 60 +
                         m_originalStartTime.time().second());
     m_currentStartTime = m_originalStartTime.addSecs(secsoffset);
+    m_threadPool.setMaxThreadCount(1);
 }
 
 bool GuideGrid::Create()
@@ -356,7 +558,6 @@ void GuideGrid::Init(void)
     updateChannels();
 
     fillProgramInfos(true);
-    updateInfo();
 
     m_updateTimer = new QTimer(this);
     connect(m_updateTimer, SIGNAL(timeout()), SLOT(updateTimeout()) );
@@ -374,6 +575,8 @@ void GuideGrid::Init(void)
 
 GuideGrid::~GuideGrid()
 {
+    GuideHelper::Wait(this);
+
     gCoreContext->removeListener(this);
 
     while (!m_programs.empty())
@@ -1075,12 +1278,7 @@ void GuideGrid::fillTimeInfos()
 
 void GuideGrid::fillProgramInfos(bool useExistingData)
 {
-    m_guideGrid->ResetData();
-
-    for (int y = 0; y < m_channelCount; ++y)
-    {
-        fillProgramRowInfos(y, useExistingData);
-    }
+    fillProgramRowInfos(-1, useExistingData);
 }
 
 ProgramList *GuideGrid::getProgramListFromProgram(int chanNum)
@@ -1106,64 +1304,123 @@ ProgramList *GuideGrid::getProgramListFromProgram(int chanNum)
     return proglist;
 }
 
-void GuideGrid::fillProgramRowInfos(unsigned int row, bool useExistingData)
+static ProgramList *CopyProglist(ProgramList *proglist)
 {
-    m_guideGrid->ResetRow(row);
-
-    // never divide by zero..
-    if (!m_guideGrid->getChannelCount() || !m_timeCount)
-        return;
+    if (!proglist)
+        return NULL;
+    ProgramList *result = new ProgramList();
+    for (ProgramList::iterator pi = proglist->begin(); pi != proglist->end(); ++pi)
+        result->push_back(new ProgramInfo(**pi));
+    return result;
+}
 
-    for (int x = 0; x < m_timeCount; ++x)
+void GuideGrid::fillProgramRowInfos(int firstRow, bool useExistingData)
+{
+    bool allRows = false;
+    int numRows = 1;
+    if (firstRow < 0)
     {
-        m_programInfos[row][x] = NULL;
+        firstRow = 0;
+        allRows = true;
+        numRows = min((int)m_channelInfos.size(), m_guideGrid->getChannelCount());
     }
+    QVector<int> chanNums;
+    QVector<ProgramList*> proglists;
 
-    if (m_channelInfos.empty())
-        return;
+    for (unsigned int i = 0; i < numRows; ++i)
+    {
+        unsigned int row = i + firstRow;
+        // never divide by zero..
+        if (!m_guideGrid->getChannelCount() || !m_timeCount)
+            return;
 
-    int chanNum = row + m_currentStartChannel;
-    if (chanNum >= (int) m_channelInfos.size())
-        chanNum -= (int) m_channelInfos.size();
-    if (chanNum >= (int) m_channelInfos.size())
-        return;
+        for (int x = 0; x < m_timeCount; ++x)
+        {
+            m_programInfos[row][x] = NULL;
+        }
 
-    if (chanNum < 0)
-        chanNum = 0;
+        if (m_channelInfos.empty())
+            return;
 
-    if (!useExistingData)
+        int chanNum = row + m_currentStartChannel;
+        if (chanNum >= (int) m_channelInfos.size())
+            chanNum -= (int) m_channelInfos.size();
+        if (chanNum >= (int) m_channelInfos.size())
+            return;
+
+        if (chanNum < 0)
+            chanNum = 0;
+
+        ProgramList *proglist = NULL;
+        if (useExistingData)
+            proglist = CopyProglist(m_programs[row]);
+        chanNums.push_back(chanNum);
+        proglists.push_back(proglist);
+    }
+    if (allRows)
     {
-        delete m_programs[row];
-        m_programs[row] = getProgramListFromProgram(chanNum);
+        for (unsigned int i = numRows; i < m_guideGrid->getChannelCount(); ++i)
+        {
+            delete m_programs[i];
+            m_programs[i] = NULL;
+            m_guideGrid->ResetRow(i);
+        }
     }
-
-    ProgramList *proglist = m_programs[row];
-    if (!proglist)
+    GuideStatus gs;
+    gs.m_firstRow = firstRow;
+    gs.m_numRows = chanNums.size();
+    gs.m_channums = chanNums;
+    gs.m_currentStartChannel = m_currentStartChannel;
+    gs.m_currentStartTime = m_currentStartTime;
+    gs.m_currentEndTime = m_currentEndTime;
+    gs.m_currentRow = m_currentRow;
+    gs.m_currentCol = m_currentCol;
+    gs.m_channelCount = m_channelCount;
+    gs.m_timeCount = m_timeCount;
+    gs.m_verticalLayout = m_verticalLayout;
+    gs.m_firstTime = m_firstTime;
+    gs.m_lastTime = m_lastTime;
+    gs.m_channelInfos_size = m_channelInfos.size();
+    gs.m_gg_programRect = m_guideGrid->GetArea();
+    gs.m_gg_channelCount = m_guideGrid->getChannelCount();
+    GuideUpdateProgramRow *closure =
+        new GuideUpdateProgramRow(this, gs, proglists);
+    m_threadPool.start(new GuideHelper(this, closure), "GuideHelper");
+}
+
+void GuideUpdateProgramRow::fillProgramRowInfosWith(int row, int chanNum, QDateTime start,
+                                                    ProgramList *proglist)
+{
+    if (row < 0 || row >= m_gs.m_channelCount ||
+        start != m_gs.m_currentStartTime)
+    {
+        delete proglist;
         return;
+    }
 
-    QDateTime ts = m_currentStartTime;
+    QDateTime ts = m_gs.m_currentStartTime;
 
     QDateTime tnow = MythDate::current();
     int progPast = 0;
-    if (tnow > m_currentEndTime)
+    if (tnow > m_gs.m_currentEndTime)
         progPast = 100;
-    else if (tnow < m_currentStartTime)
+    else if (tnow < m_gs.m_currentStartTime)
         progPast = 0;
     else
     {
-        int played = m_currentStartTime.secsTo(tnow);
-        int length = m_currentStartTime.secsTo(m_currentEndTime);
+        int played = m_gs.m_currentStartTime.secsTo(tnow);
+        int length = m_gs.m_currentStartTime.secsTo(m_gs.m_currentEndTime);
         if (length)
             progPast = played * 100 / length;
     }
 
-    m_guideGrid->SetProgPast(progPast);
+    m_progPast = progPast;
 
     ProgramList::iterator program = proglist->begin();
     vector<ProgramInfo*> unknownlist;
     bool unknown = false;
     ProgramInfo *proginfo = NULL;
-    for (int x = 0; x < m_timeCount; ++x)
+    for (int x = 0; x < m_gs.m_timeCount; ++x)
     {
         if (program != proglist->end() &&
             (ts >= (*program)->GetScheduledEndTime()))
@@ -1215,24 +1472,24 @@ void GuideGrid::fillProgramRowInfos(unsigned int row, bool useExistingData)
     for (; it != unknownlist.end(); ++it)
         proglist->push_back(*it);
 
-    MythRect programRect = m_guideGrid->GetArea();
+    MythRect programRect = m_gs.m_gg_programRect;
 
     /// use doubles to avoid large gaps at end..
     double ydifference = 0.0, xdifference = 0.0;
 
-    if (m_verticalLayout)
+    if (m_gs.m_verticalLayout)
     {
         ydifference = programRect.width() /
-            (double) m_guideGrid->getChannelCount();
+            (double) m_gs.m_gg_channelCount;
         xdifference = programRect.height() /
-            (double) m_timeCount;
+            (double) m_gs.m_timeCount;
     }
     else
     {
         ydifference = programRect.height() /
-            (double) m_guideGrid->getChannelCount();
+            (double) m_gs.m_gg_channelCount;
         xdifference = programRect.width() /
-            (double) m_timeCount;
+            (double) m_gs.m_timeCount;
     }
 
     int arrow = 0;
@@ -1242,7 +1499,7 @@ void GuideGrid::fillProgramRowInfos(unsigned int row, bool useExistingData)
     QRect tempRect;
     bool isCurrent = false;
 
-    for (int x = 0; x < m_timeCount; ++x)
+    for (int x = 0; x < m_gs.m_timeCount; ++x)
     {
         ProgramInfo *pginfo = m_programInfos[row][x];
         if (!pginfo)
@@ -1252,9 +1509,9 @@ void GuideGrid::fillProgramRowInfos(unsigned int row, bool useExistingData)
         if (pginfo->GetScheduledStartTime() != lastprog)
         {
             arrow = 0;
-            if (pginfo->GetScheduledStartTime() < m_firstTime.addSecs(-300))
+            if (pginfo->GetScheduledStartTime() < m_gs.m_firstTime.addSecs(-300))
                 arrow = arrow + 1;
-            if (pginfo->GetScheduledEndTime() > m_lastTime.addSecs(2100))
+            if (pginfo->GetScheduledEndTime() > m_gs.m_lastTime.addSecs(2100))
                 arrow = arrow + 2;
 
             if (pginfo->spread != -1)
@@ -1263,7 +1520,7 @@ void GuideGrid::fillProgramRowInfos(unsigned int row, bool useExistingData)
             }
             else
             {
-                for (int z = x + 1; z < m_timeCount; ++z)
+                for (int z = x + 1; z < m_gs.m_timeCount; ++z)
                 {
                     ProgramInfo *test = m_programInfos[row][z];
                     if (test && (test->GetScheduledStartTime() ==
@@ -1284,7 +1541,7 @@ void GuideGrid::fillProgramRowInfos(unsigned int row, bool useExistingData)
                 }
             }
 
-            if (m_verticalLayout)
+            if (m_gs.m_verticalLayout)
             {
                 tempRect = QRect((int)(row * ydifference),
                                  (int)(x * xdifference),
@@ -1305,8 +1562,8 @@ void GuideGrid::fillProgramRowInfos(unsigned int row, bool useExistingData)
             if (tempRect.bottom() + 2 >=  programRect.bottom())
                 tempRect.setBottom(programRect.bottom());
 
-            if (m_currentRow == (int)row && (m_currentCol >= x) &&
-                (m_currentCol < (x + spread)))
+            if (m_gs.m_currentRow == (int)row && (m_gs.m_currentCol >= x) &&
+                (m_gs.m_currentCol < (x + spread)))
                 isCurrent = true;
             else
                 isCurrent = false;
@@ -1349,18 +1606,19 @@ void GuideGrid::fillProgramRowInfos(unsigned int row, bool useExistingData)
                 recStat = 0;
 
             QString title = (pginfo->GetTitle() == kUnknownTitle) ?
-                                tr("Unknown", "Unknown program title") :
+                GuideGrid::tr("Unknown", "Unknown program title") :
                                 pginfo->GetTitle();
-            m_guideGrid->SetProgramInfo(
+            m_result.push_back(UIGuideElement(
                 row, cnt, tempRect, title,
                 pginfo->GetCategory(), arrow, recFlag,
-                recStat, isCurrent);
+                recStat, isCurrent));
 
             cnt++;
         }
 
         lastprog = pginfo->GetScheduledStartTime();
     }
+
 }
 
 void GuideGrid::customEvent(QEvent *event)
@@ -1374,7 +1632,6 @@ void GuideGrid::customEvent(QEvent *event)
         {
             LoadFromScheduler(m_recList);
             fillProgramInfos();
-            updateInfo();
         }
         else if (message == "STOP_VIDEO_REFRESH_TIMER")
         {
@@ -1513,6 +1770,16 @@ void GuideGrid::customEvent(QEvent *event)
         else
             ScheduleCommon::customEvent(event);
     }
+    else if (event->type() == UpdateGuideEvent::kEventType)
+    {
+        UpdateGuideEvent *uge = static_cast<UpdateGuideEvent*>(event);
+        if (uge->m_closure)
+        {
+            uge->m_closure->ExecuteUI();
+            delete uge->m_closure;
+            uge->m_closure = NULL;
+        }
+    }
 }
 
 void GuideGrid::updateDateText(void)
@@ -1524,10 +1791,48 @@ void GuideGrid::updateDateText(void)
                                                  (MythDate::kDateFull | MythDate::kSimplify)));
 }
 
+void GuideGrid::updateProgramsUI(unsigned int firstRow, int numRows,
+                                 int progPast,
+                                 const QVector<ProgramList*> &proglists,
+                                 const QVector<struct UIGuideElement> &elements)
+{
+    for (int i = 0; i < numRows; ++i)
+    {
+        int row = i + firstRow;
+        m_guideGrid->ResetRow(row);
+        if (m_programs[row] != proglists[i])
+        {
+            delete m_programs[row];
+            m_programs[row] = proglists[i];
+        }
+    }
+    m_guideGrid->SetProgPast(progPast);
+    for (int i = 0; i < elements.size(); ++i)
+    {
+        UIGuideElement r = elements[i];
+        m_guideGrid->SetProgramInfo(r.m_row, r.m_col, r.m_area, r.m_title,
+                                    r.m_category, r.m_arrow, r.m_recType,
+                                    r.m_recStat, r.m_selected);
+    }
+    for (int i = firstRow; i < firstRow + numRows; ++i)
+    {
+        for (int j = 0; j < MAX_DISPLAY_TIMES; ++j)
+            m_programInfos[i][j] = m_programInfos[i][j];
+        if (i == m_currentRow)
+            updateInfo();
+    }
+    m_guideGrid->SetRedraw();
+}
+
 void GuideGrid::updateChannels(void)
 {
-    m_channelList->Reset();
+    m_threadPool.start(new GuideHelper(this, new GuideUpdateChannels(this, m_currentStartChannel)),
+                       "GuideHelper");
+}
 
+void GuideGrid::updateChannelsNonUI(QVector<ChannelInfo *> &chinfos,
+                                    QVector<bool> &unavailables)
+{
     ChannelInfo *chinfo = GetChannelInfo(m_currentStartChannel);
 
     if (m_player)
@@ -1575,7 +1880,19 @@ void GuideGrid::updateChannels(void)
                 unavailable = (alt == m_channelInfoIdx[chanNumber]);
             }
         }
+        chinfos.push_back(chinfo);
+        unavailables.push_back(unavailable);
+    }
+}
 
+void GuideGrid::updateChannelsUI(const QVector<ChannelInfo *> &chinfos,
+                                 const QVector<bool> &unavailables)
+{
+    m_channelList->Reset();
+    for (int i = 0; i < chinfos.size(); ++i)
+    {
+        ChannelInfo *chinfo = chinfos[i];
+        bool unavailable = unavailables[i];
         MythUIButtonListItem *item =
             new MythUIButtonListItem(m_channelList,
                                      chinfo ? chinfo->GetFormatted(ChannelInfo::kChannelShort) : QString());
@@ -1660,6 +1977,7 @@ void GuideGrid::updateInfo(void)
         QString rating = QString::number(pginfo->GetStars(10));
         ratingState->DisplayState(rating);
     }
+    m_guideGrid->SetRedraw();
 }
 
 void GuideGrid::toggleGuideListing()
@@ -1809,9 +2127,7 @@ void GuideGrid::cursorLeft()
     }
     else
     {
-        fillProgramRowInfos(m_currentRow);
-        m_guideGrid->SetRedraw();
-        updateInfo();
+        fillProgramRowInfos(m_currentRow, true);
     }
 }
 
@@ -1837,9 +2153,7 @@ void GuideGrid::cursorRight()
     }
     else
     {
-        fillProgramRowInfos(m_currentRow);
-        m_guideGrid->SetRedraw();
-        updateInfo();
+        fillProgramRowInfos(m_currentRow, true);
     }
 }
 
@@ -1854,10 +2168,7 @@ void GuideGrid::cursorDown()
     }
     else
     {
-        fillProgramRowInfos(m_currentRow);
-        m_guideGrid->SetRedraw();
-        updateInfo();
-        updateChannels();
+        fillProgramRowInfos(m_currentRow, true);
     }
 }
 
@@ -1872,10 +2183,7 @@ void GuideGrid::cursorUp()
     }
     else
     {
-        fillProgramRowInfos(m_currentRow);
-        m_guideGrid->SetRedraw();
-        updateInfo();
-        updateChannels();
+        fillProgramRowInfos(m_currentRow, true);
     }
 }
 
@@ -1907,8 +2215,6 @@ void GuideGrid::moveLeftRight(MoveVector movement)
 
     fillTimeInfos();
     fillProgramInfos();
-    m_guideGrid->SetRedraw();
-    updateInfo();
     updateDateText();
 }
 
@@ -1933,8 +2239,6 @@ void GuideGrid::moveUpDown(MoveVector movement)
     }
 
     fillProgramInfos();
-    m_guideGrid->SetRedraw();
-    updateInfo();
     updateChannels();
 }
 
@@ -1947,8 +2251,6 @@ void GuideGrid::moveToTime(QDateTime datetime)
 
     fillTimeInfos();
     fillProgramInfos();
-    m_guideGrid->SetRedraw();
-    updateInfo();
     updateDateText();
 }
 
@@ -2016,7 +2318,6 @@ void GuideGrid::quickRecord()
     QuickRecord(pginfo);
     LoadFromScheduler(m_recList);
     fillProgramInfos();
-    updateInfo();
 }
 
 void GuideGrid::editRecSchedule()
@@ -2163,7 +2464,6 @@ void GuideGrid::GoTo(int start, int cur_row)
     m_currentRow = cur_row % m_channelCount;
     updateChannels();
     fillProgramInfos();
-    updateInfo();
     updateJumpToChannel();
 }
 
diff --git a/mythtv/programs/mythfrontend/guidegrid.h b/mythtv/programs/mythfrontend/guidegrid.h
index fd11d27..665d4ea 100644
--- a/mythtv/programs/mythfrontend/guidegrid.h
+++ b/mythtv/programs/mythfrontend/guidegrid.h
@@ -17,6 +17,7 @@ using namespace std;
 #include "channelgroup.h"
 #include "channelutil.h"
 #include "mythuiguidegrid.h"
+#include "mthreadpool.h"
 
 // mythfrontend
 #include "schedulecommon.h"
@@ -102,6 +103,11 @@ class GuideGrid : public ScheduleCommon, public JumpToChannelListener
 
     virtual void aboutToShow();
     virtual void aboutToHide();
+    // Allow class GuideUpdateProgramRow to figure out whether the
+    // current start time/channel coordinates are the same, so that it can
+    // skip the work if not.
+    uint GetCurrentStartChannel(void) const { return m_currentStartChannel; }
+    QDateTime GetCurrentStartTime(void) const { return m_currentStartTime; }
 
   protected slots:
     void cursorLeft();
@@ -179,8 +185,20 @@ class GuideGrid : public ScheduleCommon, public JumpToChannelListener
     void fillChannelInfos(bool gotostartchannel = true);
     void fillTimeInfos(void);
     void fillProgramInfos(bool useExistingData = false);
-    void fillProgramRowInfos(unsigned int row, bool useExistingData = false);
+    // Set row=-1 to fill all rows.
+    void fillProgramRowInfos(int row, bool useExistingData);
+public:
+    // These need to be public so that the helper classes can operate.
     ProgramList *getProgramListFromProgram(int chanNum);
+    void updateProgramsUI(unsigned int firstRow, int numRows,
+                          int progPast,
+                          const QVector<ProgramList*> &proglists,
+                          const QVector<struct UIGuideElement> &elements);
+    void updateChannelsNonUI(QVector<ChannelInfo *> &chinfos,
+                             QVector<bool> &unavailables);
+    void updateChannelsUI(const QVector<ChannelInfo *> &chinfos,
+                          const QVector<bool> &unavailables);
+private:
 
     void setStartChannel(int newStartChannel);
 
@@ -235,6 +253,8 @@ class GuideGrid : public ScheduleCommon, public JumpToChannelListener
 
     QTimer *m_updateTimer; // audited ref #5318
 
+    MThreadPool       m_threadPool;
+
     int               m_changrpid;
     ChannelGroupList  m_changrplist;
 
