質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.07%

マルチスレッド処理(非同期)をしたいのですが、エラーコードC2893が消えません。

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 252

Ta_42

score 1

前提・実現したいこと

画像処理の勉強をしており、マルチスレッドを使って複数の動作を同時に行いたいと考えております。
すでに動作確認済みの二つのプログラムをマルチスレッドで行ったところ以下2点のエラーが出ました。

素人判断ですが、関数たちはもともと動いていたため悪さをしていないと思い簡素なコードを載せております。判断に必要なデータがありましたら教えてください。

発生している問題・エラーメッセージ

error C2893: 関数テンプレート 'unknown-type std::invoke(_Callable &&,_Types &&...) noexcept(<expr>)' の特定に失敗しました
error C2672: 'std::invoke': 一致するオーバーロードされた関数が見つかりませんでした。

該当のソースコード

#include <librealsense2/rs.hpp> // Include RealSense Cross Platform API
#include <opencv2/opencv.hpp> 
#include <fstream>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <thread>

int ThradProcess1(int argc, char* argv[]) try {

  画像を表示するプログラム。

    }

    return EXIT_SUCCESS;
}
catch (const rs2::error& e)
{
    std::cerr << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n    " << e.what() << std::endl;
    return EXIT_FAILURE;
}
catch (const std::exception& e)
{
    std::cerr << e.what() << std::endl;
    return EXIT_FAILURE;
}

void save_frame_depth_data(const std::string& filename,
    rs2::frame frame,
    float depth_units)
{
   csvファイルに画像の距離情報を書きこむプログラム
}


int ThradProcess2(int argc, char* argv[]) try
{
  ・
  ・
  ・
    while (true) 
    {
    .
    .
    .
    //csvファイルに画像の距離情報を書きこむ関数の呼び出し
        save_frame_depth_data("depth", depth, depth_units);

    }

    return EXIT_SUCCESS;
}
catch (const rs2::error& e)
{
    std::cerr << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n    " << e.what() << std::endl;
    return EXIT_FAILURE;
}
catch (const std::exception& e)
{
    std::cerr << e.what() << std::endl;
    return EXIT_FAILURE;
}

int main() {
    std::thread th1(ThradProcess1);
    std::thread th2(ThradProcess2);

    th1.join();
    th2.join();
}

補足情報(FW/ツールのバージョンなど)

  1. OS:Windows10
  2. IDE:Microsoft Visual Studio Community 2019
  3. 開発言語:C++

当方、プログラム並びにTeratail質問初心者なため
基本的な間違いや失礼がありましたらそちらもご教授いただけると幸いです。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • KoichiSugiyama

    2020/06/22 19:01

    検索ワード「error C2672 std::invoke」で検索するといろいろなサイトがヒットしますが、試してダメだったものがありますでしょうか。もしあるようでしたらそれを明記していただいた方が、アドバイスする側も余計な回り道をしなくて済むと思います。

    キャンセル

  • Ta_42

    2020/06/22 21:11

    ご指摘ありがとうございます。
    調べても理解が追いつかずこちらに質問した次第で、何かを試すまでには至っておりません。
    抽象度の高い質問で申し訳ないのですが、お力添えいただけると幸いです。

    キャンセル

回答 1

checkベストアンサー

0

int ThradProcess1(int argc, char* argv[])
int ThradProcess2(int argc, char* argv[])

なんだから、スレッドには引数与えにゃならんのでしょ?

   std::thread th1(ThradProcess1);
   std::thread th2(ThradProcess2);

ここで引数食わせてあげなよ。

おそらくは:

int main(int argc, char* argv[]) {
    std::thread th1(ThradProcess1, argc, argv);
    std::thread th2(ThradProcess2, argc, argv);

    th1.join();
    th2.join();
}


[追記] こんなことがやりたいのかな:

#define  _CRT_SECURE_NO_WARNINGS
#include <thread>
#include <iostream>
#include <string>
#include <cstring>

int ThradProcess1(int argc, char* argv[]) {
  if ( argc < 2 ) return -1;
  for ( int i = 1; i < argc; ++i ) {
    std::cout << (std::string(argv[0]) + " は " + argv[i] + " を画面に描くよ!\n");
  }
  return 0;
}

int ThradProcess2(int argc, char* argv[]) {
    if (argc < 3) return -1;
    std::cout << (std::string(argv[0]) + " は " +
                  argv[1] + " の距離情報を " + 
                  argv[2] + " に書き込むよ\n");
    return 0;
}

int make_argv(char* commandline, char* argv[]) {
  int argc = 0;
  for ( char* token = strtok(commandline, " "); token; token = strtok(NULL, " ")) {
    argv[argc++] = token;
  }
  return argc;
}

int main() {
  char command1[] = "ThreadProcess1 picture.png";
  char* argv1[8];
  int argc1 = make_argv(command1, argv1);
  std::thread thread1(ThradProcess1, argc1, argv1);

  char command2[] = "ThreadProcess2 objects.png distance.csv";
  char* argv2[8];
  int argc2 = make_argv(command2, argv2);
  std::thread thread2(ThradProcess2, argc2, argv2);

  thread1.join();
  thread2.join();
  std::cout << "おしごとおしまい\n";
}


実行結果:

ThreadProcess1 は picture.png を画面に描くよ!
ThreadProcess2 は objects.png の距離情報を distance.csv に書き込むよ
おしごとおしまい

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/06/23 22:23

    コマンドラインからではなく、直接ファイルを開いて動かしていたので
    特に、引数を食わせることはしてなかったです。習わし程度に(int argc, char* argv[])と書いていたもので…

    episteme様のご指摘通り訂正を加えるとビルドできたのですが、実行の仕方で挙動が異なる結果となります。具体的には、

    コマンドプロンプトから実行:
    ”画像のデータをファイルに書き起こし”のみ起動、”画像のストリーミング””はウィンドウだけ表示されて映像なし

    フォルダから直接実行:
    ””画像のデータをファイルに書き起こし”は動かず、”画像のストリーミング””は正常に作動

    つまり、どちらかのスレッドしか動いていないという状況になりました。これは、二つのスレッド同士で同じデータを使おうとして起きているという別問題かもしれません。

    当初の質問は解決したと思はれるのですが、こういう場合は一度閉じて
    別の質問を立てるべきでしょうか?
    プログラムに関係ない質問で申し訳ありません。

    キャンセル

  • 2020/06/24 07:39

    > 引数を食わせることはしてなかったです。
    なら void ThreadProcess() { ... } で十分。

    > これは、二つのスレッド同士で同じデータを使おうとして起きているという別問題かもしれません。
    それぞれが異なるファイルを処理対象とすれば状況は変わるかもですね。

    > こういう場合は一度閉じて別の質問を立てるべきでしょうか?
    コンパイル・エラーは解消されましたからねぇ...

    キャンセル

  • 2020/06/24 20:31

    では、episteme様の回答をベストアンサーに選ばせていただき
    この質問を終わりたいと思います。

    知識の浅さ丸出しの質問にも関わらず、丁寧にお答えいただきありがとうございます。助かりました。
    追記の内容も(int argc, char* argv[])の用途を理解するのにとても分かりやすかったです。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.07%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問