0

私のアプリケーションでは、別のアプリケーションが開始または停止されたことをイベントで通知したいと考えています。私は実行中のアプリケーションに既存の API を持っていますが、これは明らかな解決策である通知に対応するために変更することはできません。

私が持っているのは API の関数呼び出し (isRunning) であるため、API を介して状態をポーリングし、アプリに通知するポーリング スレッドを作成することにしました。

私の問題は、ポーリング スレッドでの API 呼び出しが、自分のアプリケーションのメイン スレッドでも使用されているオブジェクトを使用していることです。それを確実に正しく行う方法を知りたいです :)。

私のアイデアは、API オブジェクトへの各呼び出しを (アダプターを介して、たとえば 2 番目のコード ブロックを参照) ミューテックス ロックでラップすることです。そのため、API が私のスレッドによって複数回呼び出されることはないと確信しています。

これは正しいアプローチですか?

スレッド化/同期にブーストを使用しています (コードを参照)。

これはポーリング スレッドです。

void EventCreator::start()
{
    stop();
    m_bShouldRun = true;    
    m_spThread = BoostThreadPtr(new thread(bind(&EventCreator::run,this)));
}

void EventCreator::stop()
{
    {
        lock_guard<mutex> lock(m_mutex);
        m_bShouldRun = false;
        m_condition.notify_one();
    }

    if (m_spThread)
    {
        m_spThread->join();
        m_spThread.reset();
    }    
}

void EventCreator::run()
{
    bool isRTAppRunning = m_pDevice->isApplicationRunning();
    while (m_bShouldRun)
    {
        boost::unique_lock<mutex> lock(m_mutex);
        // 
        if(!m_condition.timed_wait(lock,boost::system_time(boost::get_system_time() + boost::posix_time::milliseconds(25))))
        {
            // here because of time out, so no sleep necessary
            bool isStillRunning = m_pDevice->isApplicationRunning();
            if (isRTAppRunning != isStillRunning)
            {   

                if (isStillRunning)
                {
                    // Using SendMessage to main thread => no problem here
                    notifyAppStarted();
                }
                else
                {   
                    notifyAppStopped(); 
                }
                isRTAppRunning = isStillRunning;
            }
            // in addition to wait above
            m_spThread->yield();
        }
    }
}

これらは、メイン スレッドからのいくつかの API 呼び出しです。

void Device::getData(Int32 byteCnt)
{
    mutex::scoped_lock lock(m_monitor);
    m_pApi->fetchBytes(&m_buf,byteCnt);
}

bool Device::isApplicationRunning()
{
    mutex::scoped_lock lock(m_monitor);
    return m_pApi->getState() == DV_RUNNING;
}
4

1 に答える 1

0

これは良いアプローチのように思えます。

一般に、競合していない場合、ロックは非常に高速に取得できます。ポーリング スレッドは頻繁にポーリングしないようにする必要があります。つまり、多くても数秒に 1 回の頻度でポーリングする必要があるため、ロックの競合は非常に小さいはずです。

2 つのスレッドが常にロックをめぐって争っている場合は、設計を再考する必要があります。

于 2009-03-20T19:08:26.987 に答える