2

編集2:問題は解決しました。私の答えを参照してください。

EngineAPIを介してMATLABと通信するC++プログラムを作成しています。C++アプリケーションはWindows7で実行されており、MATLAB 2012b(32ビット)と対話します。

を使用してMATLABエンジンに時間のかかる呼び出しを行いengEvalStringたいのですが、呼び出しを非同期にする方法がわかりません。コールバックは必要ありません(ただし、可能であればいいでしょう)。

以下は、機能しないものの最小限の例です。

#include <boost/thread.hpp>

extern "C" {
    #include <engine.h>
}

int main()
{
    Engine* eng = engOpen("");
    engEvalString(eng,"x=10");
    boost::thread asyncEval(&engEvalString,eng,"y=5");
    boost::this_thread::sleep(boost::posix_time::seconds(10));
    return 0;
}

このプログラムを実行した後、MATLABエンジンウィンドウに切り替えて、次のことを見つけます。

» x
x =
    10
» y
Undefined function or variable 'y'.

したがって、y = 5に設定する必要がある2番目の呼び出しは、MATLABエンジンによって処理されないようです。

スレッドは確実に実行されます。engEvalString呼び出しをローカル関数に移動し、代わりにスレッドとして起動することで、これを確認できます。

私はここで本当に困惑しています、そしてどんな提案でもありがたいです!

編集: Shafikが彼の答えで指摘したように、エンジンはスレッドセーフではありません。私が行う必要のある呼び出しは2秒かかる計算の場合、約5秒離れているため、これが私のユースケースの問題になるとは思わない。この計算が待ちきれない理由は、C++アプリケーションが「ミディアムハード」のリアルタイムロボットコントローラーであり、50Hzでコマンドを送信する必要があるためです。このレートが30Hzを下回ると、ロボットはネットワークの問題を想定して接続を閉じます。

4

2 に答える 2

1

それで、私は問題を理解しましたが、誰かが理由を説明できれば幸いです!

以下の作品:

#include <boost/thread.hpp>

extern "C" {
#include <engine.h>
}

void asyncEvalString()
{
    Engine* eng = engOpen("");
    engEvalString(eng,"y=5");
}

int main()
{
    Engine* eng = engOpen("");
    engEvalString(eng,"x=10");
    boost::thread asyncEvalString(&asyncEvalString);
    boost::this_thread::sleep(boost::posix_time::seconds(1));
    engEvalString(eng,"z=15");
    return 0;
}

ご覧のとおり、新しいスレッドでエンジンへの新しいポインターを取得する必要があります。で返されるポインタは、main 関数でasyncEvalString返される元のポインタとは異なりますがengOpen、どちらのポインタも問題なく動作し続けます。

» x
x =
    10
» y
y =
     5
» z
z =
    15

最後に、スレッド セーフの問題に取り組むために、engEvalString 呼び出しの周りにミューテックスを設定して、一度に 1 つのスレッドだけがエンジンを使用するようにすることができます。asyncEvalString 関数を変更して、engEvalString 関数が完了したらコールバック関数をトリガーすることもできます。

ただし、上記のソリューションが機能する理由を誰かが説明していただければ幸いです。Engine*スレッドはプロセスのヒープ割り当てメモリを共有し、他のスレッドのスタック (?) のメモリにアクセスできるため、別のスレッドで使用すると最初のスレッドが突然無効になる理由がわかりません。

于 2013-02-26T22:42:04.633 に答える
1

したがって、このMathworksドキュメントによると、スレッドセーフではないため、これが機能するとは思えません。

http://www.mathworks.com/help/matlab/matlab_external/using-matlab-engine.html

このドキュメントによると、engOpen は新しいプロセスをフォークします。これにより、表示されている残りの動作が説明される可能性があります。

http://www.mathworks.com/help/matlab/apiref/engopen.html

また、スレッドとフォークを参照してください。それらを混合することについてよく考えてください。

http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them

于 2013-02-26T21:48:50.150 に答える