2016-05-09 17 views
0

C++ win 32アプリケーション。 VS 2013 私は第三者図書館を利用しています。 サードパーティライブラリの機能をバックグラウンドスレッドで呼びたいと思っています。 私はまた、最終的にそれをオフにしたいと思います。 私は、アプリケーションが存在する前に、サードパーティに十分な時間を与えないでください。 main()を終了する前に、別のスレッドで開始した分離タスクを確実に行う方法を教えてください。ここで C++アプリケーションを終了する前にバックグラウンドスレッドを終了させる

//this class interfaces with the third part and runs on a separate thread 
class ThirdParty 
{ 

    void Start(std::string filename) 
    { 
     MyApplication application; 
     FIX::SessionSettings settings(filename); 
     FIX::FileStoreFactory storeFactory(settings); 
     FIX::ScreenLogFactory logFactory(settings); 
     FIX::SocketAcceptor acceptor(application, storeFactory, settings, logFactory); 
     acceptor.start(); //this third party internally starts new threads and does stuff thats transparent to consumer like myself. 
     while (m_runEngine) 
       {} 


//this shutsdown a few things and cant execute instantaneously 
//This does not finish execution and main() already ends. 
     acceptor.stop(); 
    } 
    void Stop() 
    { 
     m_runEngine = false; 
    } 
private: 
bool m_runEngine{ true }; 

} 

はWin32アプリケーションでは()私のメインである

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    std::wstring arg = argv[1]; 
    std::string filename = std::string(arg.begin(), arg.end()); 
    ThirdParty myprocess; 

    std::thread t(&ThirdParty::Start, &myprocess, filename); 

    t.detach(); 

    while (true) 
    { 
     std::string value; 
     std::cin >> value; 
     if (value == "quit") 
      break; 
    } 

    myprocess.Stop(); //This line will execute really fast and application will exit without allowing acceptor.stop() to properly finish execution 
//How can I ensure acceptor.stop() has finished execution before I move on to the next line and finish the application 

    return 0; 
} 
+3

スレッドを取り外さないでください。代わりに、参加可能にしてから終了してから終了してください。 Windows上にいるので、ネイティブスレッドハンドルを取得し、有意義なタイムアウトでイベントを待機し、イベントがトリガーされた場合に参加します。それ以外の場合は、エラーを報告して終了してください。 – SergeyA

+0

私はそれを得る。 t.detach()の代わりにt.joinable()を呼び出し、最後にmyprocess.stop()の後にt.join()を呼び出します。それは私のデバッガで動作するようです。他のオプションも試してみます。 – bsobaid

+0

t.joinable()を呼び出す必要はなく、joinableであることがわかります。ネイティブ・ジョインの問題は、スレッドが応答しなくなった場合(ループに詰まったり、リソースにロックされているなど)、アプリケーションが停止してしまうことです。これがシャットダウンする時間を与える価値がある理由ですが、できない場合は、forcefulyを終了してください(エラーが発生した場合)。 – SergeyA

答えて

1

それはthread::join()使用して終了するためにあなたが待つことができるようにあなたは、切り離されたスレッドにしないでください:

//t.detach() do not detach thread 
... 
myprocess.Stop(); 
t.join(); // wait for t to end 
+0

Sergeyは最初にそれに答えましたが、私はコメントだけをアップvoteすることができますので、答えとしてあなたの正解をチェックします。 – bsobaid

+0

セルゲイは私もあなたも責めません:) – shrike

+1

m_runEngineを 'std :: atomic'にしたり、mutexでガードしたりしない限り、実際にそれが読み込まれるという保証はありません。コンパイラは自由にそのコードを見て、 "ああ...このループでこの変数を変更する方法はありません - while(true){}"に最適化してください。 'std :: atomic'は、基本的に変数が常にメモリ位置から読み込まれ、mutexはより重い重みを持ちますが、人々が読むと予想しているものに近いことを意味します。 – Charlie

0

次の例は、スレッド結合の興味深い側面を示しています。

void pause_thread(int n, std::string lbl) 
{ 
    std::this_thread::sleep_for (std::chrono::seconds(n)); 
    std::cout << lbl << " pause of " << n << " seconds ended" << std::endl; 
} 

int t403(void) // in context of thread main 
{ 
    std::cout << "Spawning 3 threads...\n" << std::flush; 
    std::thread t1 (pause_thread, 3, "t1"); 
    std::thread t2 (pause_thread, 2, "t2"); 
    std::thread t3 (pause_thread, 1, "t3"); 
    std::cout << "Done spawning threads, " 
     "Note that the threads finish out-of-order. \n" 
     "Now 'main' thread waits for spawned threads to join:\n" << std::flush; 

    t1.join(); std::cout << "join t1 " << std::flush; 
    t2.join(); std::cout << "join t2 " << std::flush; 
    t3.join(); std::cout << "join t3 " << std::flush; 
    std::cout << "completed join \n" 
     "note: \n - join sequence is in-order, but finish sequence is out-of-order\n" 
     " - inference: the threads waited in join main. "<< std::endl; 

    return(0); 
} 

スレッドは、t1、t2、t3の順序で生成されることに注意してください。

スレッドの終了順序が異なることに注意してください。

しかし、メインが待っているので、参加はまだ起動順序になっています。

'std :: flush()'を使用すると、人間の視覚に十分ゆっくりと選択されたタイムラインが表示されます。

+0

Linuxからの例 –

関連する問題