2016-10-27 36 views
0

C++のedsdk開発にマルチヘッドを追加しようとしましたが、takePictures()で "takeSinglePicture()"を実行するとコードがスタックしてしまい、カメラは一枚も撮られません。これを修正してください。コードはここにあります。C++のCanon EDSDK MultiThreading

一般的なノートで
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 

} 

答えて

0

、キヤノンSDKはスレッドセーフではなく、別のスレッドでSDKの関数を呼び出す前に、あなたは、Windows上のCoInitializeExを呼び出す必要があります(とわからない他のコマンドが同時に実行されていることを確認します) 。

この特定のケースでは、takePicturesMTと同じスレッドでCanon SDKを初期化した可能性が最も高いです。 Canon SDKは、初期化スレッドをメインスレッドとして使用し、そこですべてのコマンドを実行します。これは、メインスレッドでコマンドを実行しようとするtakeSinglePictureコマンドを呼び出そうとしていることを意味し、メインスレッドはtakePicturesスレッドが終了するのを待って - >デッドロックします。

解決策は、スレッドが終了するのを待つか(cameraThread.joinなし)、別のスレッドでSDKを初期化することです。 2番目の解決策は、(EdsGetEvent関数を使用して)独自のメッセージポンプを実装する必要があり、SDK関数を呼び出す場所から慎重にする必要があるため、かなり難しいです。また、SDKのメインスレッドは常にアプリケーションのメインスレッド(どこから初期化されているかにかかわらず)であるため、macOSでは動作しません。