2017-08-29 5 views
0

Je me demandais s'il était possible de créer un indicateur de progression animé qui ne sera pas gelé tant qu'une opération est en cours dans le thread principal. Je pensais que peut-être créer un deuxième fil et l'utiliser pour afficher un simple dialogue (wxGenericProgressDialog dans ce cas) permettrait de résoudre le problème. J'ai essayé plusieurs approches, mais toutes ont échoué. Il y a un exemple simple:Afficher l'indicateur de progression dans un autre thread à l'aide de wxWidgets

class ThreadTester : public wxThread { 
public: 
    ThreadTester(wxMutex *mutex, wxCondition *condition) 
    { 
     m_mutex = mutex; 
     m_condition = condition; 
    } 

    virtual wxThread::ExitCode Entry() override { 

     // This is usually non-blocking operation - this window 
     // is by default non-modal 
     d = new wxGenericProgressDialog("test1", "test2", 100, 0); 

     wxMutexLocker lock(*m_mutex); 
     m_condition->Broadcast(); 

     return nullptr; 
    } 

private: 
    wxCondition *m_condition; 
    wxMutex *m_mutex; 

    wxGenericProgressDialog *d; 
}; 

void MyFrame::PerformSomeTimeConsumingOperation(wxCommandEvent& event) 
{ 

    wxMutex mutex; 
    wxCondition condition(mutex); 

    mutex.Lock(); 

    auto t = new ThreadTester(&mutex, &condition); 
    t->Run(); 

    // Wait until showing dialog is completed 
    condition.Wait(); 

    // Perform some time-consuming operation here 

    // Kill thread (and hide the dialog) after the operation is completed 
    t->Kill(); 

} 

Lorsque je supprime cette ligne

d = new wxGenericProgressDialog("test1", "test2", 100, 0); 

il fonctionne très bien. C'est pourquoi j'ai commencé à penser que créer un dialogue avec wxWidgets (même sans parent) nécessite une attention particulière du thread principal. Et c'est pourquoi il n'est pas possible de créer un dialogue dans un autre thread lorsque le thread principal est bloqué. Est-ce exact? Est-ce que quelqu'un a réalisé ce que je veux faire? Je sais que la façon recommandée de faire cela serait de déplacer une opération fastidieuse vers un autre thread et de mettre gui-handling dans le thread principal, mais comme cela nécessiterait la refonte de certaines parties de mon application, j'ai décidé de l'essayer de cette façon en premier.

Répondre

1

Vous devez changer d'approche - effectuer une tâche longue sur un thread secondaire et effectuer des mises à jour/actualisations de l'interface graphique dans le main. La façon dont vous pensez du problème est incorrecte - les threads existent explicitement pour résoudre ce problème - exécutez une tâche longue pendant que le thread principal est en cours d'exécution.

De plus, votre approche ne garantit pas de travailler sur l'une des 3 plates-formes principales supportées par wxWidgets.

Ligne inférieure - effectue une tâche dans un thread et envoie un événement de notification pour mettre à jour l'interface graphique principale.