0

時限スレッドを実行する次のコードがあります。

// Method to invoke a request with a timeout.
bool devices::server::CDeviceServer::invokeWithTimeout(CDeviceClientRequest&  request,
                                                       CDeviceServerResponse& response)
{
   // Retrieve the timeout from the device.
   int timeout = getTimeout();
   timeout += 500; // Add 500ms to cover invocation time.

   // Invoke the request within a timed thread.
   boost::promise<void>        boostPromise;
   boost::unique_future<void>  boostFuture = boostPromise.get_future();
   boost::thread               boostThread([&]()
                               {
                                  invoke(request, response); 
                                  boostPromise.set_value();
                               });

   // The thread has timed out, if the future is not ready.
   return (boostFuture.wait_for(boost::chrono::milliseconds(timeout)) 
           == 
           boost::future_status::ready);
}

これは問題なく動作しているように見えます。タイムアウトすると、関数は false を返します。

ただし、(invoke(request, response); によって) 呼び出されるコードは、アプリケーションを強制終了する例外をスローします。スレッドが完了していない場合にスレッドを正常に終了し、例外を消費するにはどうすればよいですか。

私は次のことを試しました:

// The thread has timed out, if the future is not ready.
bool completed = (boostFuture.wait_for(boost::chrono::milliseconds(timeout)) 
                  == 
                  boost::future_status::ready);
if (!completed)
{
   boostThread.interrupt();
}
return completed;

ただし、これも例外をスローし、アプリケーションをクラッシュさせます。タイムアウトに達した場合に、時間指定されたスレッドを安全に強制終了できる完全に安全なメカニズムが必要です。

4

2 に答える 2

1

ブーストのドキュメントの状態:

boost::thread コンストラクターに渡された関数または呼び出し可能オブジェクトが呼び出されたときに、boost::thread_interrupted 型ではない例外を伝播する場合、std::terminate() が呼び出されます。

例外をキャッチし、スレッドを正常に終了する (または boost::thread_interrupted をスローする) 必要があります。

http://www.boost.org/doc/libs/1_54_0/doc/html/thread/thread_management.html#thread.thread_management.tutorial.exceptions

于 2013-08-12T17:58:55.687 に答える
0

OK、解決策として思いついたコードは次のとおりです。

// Functor to help invoke the device method, inside a timed thread.
struct invoke_fn
{
   void operator()(devices::server::CDeviceServer& server,
                   boost::promise<void>&           boostPromise,
                   CDeviceClientRequest&           request,
                   CDeviceServerResponse&          response)
   {
      try
      {
         server.invoke(request, response);
         boostPromise.set_value();
      }
      catch (devices::util::CDeviceException &e)
      {
         // Add any error to the response.
         std::string message = devices::util::retrieveDeviceExceptionMessage(e);
         response.set_errormessage(message);
      }
      catch (std::exception &e)
      {
         // Add any exception message to the response.
         std::string message(e.what());
         response.set_errormessage(message);
      }
   }
};

// Method to invoke a request with a timeout.
bool devices::server::CDeviceServer::invokeWithTimeout(CDeviceClientRequest&  request,
                                                       CDeviceServerResponse& response)
{
   // Retrieve the timeout from the device.
   int timeout = getTimeout();
   timeout += 500; // Add 500ms to cover invocation time.

   // Invoke the request within a timed thread.
   boost::promise<void>        boostPromise;
   boost::unique_future<void>  boostFuture = boostPromise.get_future();
   boost::thread               boostThread([&]()
                               {
                                  invoke_fn functor;
                                  functor(*this,
                                          boostPromise,
                                          request,
                                          response);
                               });

   // The thread has timed out, if the future is not ready.
   return (boostFuture.wait_for(boost::chrono::milliseconds(timeout)) 
           == 
           boost::future_status::ready);
}
于 2013-08-13T12:42:28.120 に答える