2016-10-27 4 views
0

J'essaie d'ajouter du développement multitheading à edsdk en C++ mais le code reste bloqué lors de l'exécution de "takeSinglePicture()" dans "takePictures()", et la caméra ne prend même pas une seule image. réparez ceci.le code est ici.Canon EDSDK MultiThreading en C++

void CameraControl::takePictures(int n,int time) { 
    openSession(); 
    CTimer timer; 
    for (int i = 0; i < n; i++) { 
     timer.start(); 
     std::cout<<std::this_thread::get_id()<<endl; 
     takeSinglePicture(); 
     int t = timer.stop(); 
     if (t < time) std::this_thread::sleep_for(std::chrono::milliseconds(time-t)); 
     std::cout << t << std::endl; 
    } 
    closeSession(); 

} 


void CameraControl::takePicturesMT(int n,int time) { 
    std::cout << std::this_thread::get_id() << endl; 
    std::thread cameraThread([&] {CameraControl::takePictures(n,time); }); 
    cameraThread.join(); 
} 

void CameraControl::takeSinglePicture() { 
    EdsSendCommand(theCamera, kEdsCameraCommand_PressShutterButton, 1); // Half 
    EdsSendCommand(theCamera, kEdsCameraCommand_PressShutterButton, 3); // Completely 
    EdsSendCommand(theCamera, kEdsCameraCommand_PressShutterButton, 0); // Off 

} 

Répondre

0

Sur une note générale, le SDK Canon est pas thread-safe et avant d'appeler une fonction SDK sur un thread différent vous devez appeler CoInitializeEx sur Windows (et assurez-vous pas une autre commande est exécutée en même temps) .

Dans ce cas spécifique, il est très probable que vous ayez initialisé le SDK Canon sur le même thread que vous appelez takePicturesMT. Canon SDK utilise le thread initialize comme thread principal et exécute toutes les commandes à cet endroit. Cela signifie que vous essayez d'appeler la commande takeSinglePicture, qui essaie d'exécuter la commande sur le thread principal et le thread principal attend que le thread takePictures finisse -> deadlock.

La solution consiste à ne pas attendre la fin du thread (pas de cameraThread.join) ou à initialiser le SDK sur un thread différent. La deuxième solution est un peu plus difficile car vous devez alors implémenter votre propre pompe de message (avec la fonction EdsGetEvent) et faire attention à l'endroit où vous appelez les fonctions du SDK. Il ne fonctionne pas non plus sur macOS car le thread principal du SDK est toujours le thread principal des applications (quel que soit l'endroit où vous initialisez).