2

リストからコマンドを実行するスレッドがあります

do
{
    commandExec->criticalSection.EnterCS();
    if (!commandExec->commands.empty())
    {
        commandExec->ExecuteCommand(commandExec->commands.front());
        commandExec->commands.pop_front();
    }
    else
        commandExec->criticalSection.SuspendThread();
    commandExec->criticalSection.LeaveCS();
} while (commandExec->maintainCommandExecution);

リストにコマンドを追加する2番目のスレッド:

criticalSection.EnterCS();
commands.push_back(Command(code, parameters));
criticalSection.LeaveCS();
criticalSection.ResumeThread();

コマンドの実行中に最初のスレッドがクラッシュする可能性があるため、2番目のスレッドがクリティカルセクションにアクセスできませんでした。

スレッドがクリティカルセクションの所有権を持っている間に終了した場合、クリティカルセクションの状態は未定義です。 ソース

それで、この問題を処理するための良い方法は何ですか? 私はいくつかの解決策を考えることができましたが、それらはトリッキーなようです(3番目のスレッド、2番目のクリティカルセクションなどを追加する)

(criticalSectionは、CRITICAL_SECTIONの単純なラッパーです)

4

2 に答える 2

2

クリティカルセクションの代わりにミューテックスを使用できます(ただし、WAIT_ABANDONEDの結果の理解で概説されている問題に注意してください)。

于 2012-11-07T23:46:14.060 に答える
2

クラスLockCriticalSectionを作成できます。このクラスは、コンストラクターのクリティカルセクションをロックし、デストラクタのクリティカルセクションのロックを解除します。

次に、コードで、ロックを開始する場所にLockCriticalSectionオブジェクトを割り当てます。オブジェクトLockCriticalSectionがスコープ外になると、クリティカルセクションが自動的に解放されます(関数が正しく終了するため、または例外のため)

以下は、クリティカルセクションのロックとロック解除を処理するコードです。

/// \brief This class locks a critical section in the
///         constructor and unlocks it in the destructor.
///
/// This helps to correctly release a critical section in
///  case of exceptions or premature exit from a function
///  that uses the critical section.
///
///////////////////////////////////////////////////////////
class LockCriticalSection
{
public:
        /// \brief Creates the object LockCriticalSection and
        ///         lock the specified CRITICAL_SECTION.
        ///
        /// @param pCriticalSection pointer to the CRITICAL_SECTION 
        ///                         to lock
        ///
        ///////////////////////////////////////////////////////////
        LockCriticalSection(CRITICAL_SECTION* pCriticalSection):
            m_pCriticalSection(pCriticalSection)
        {
            EnterCriticalSection(pCriticalSection);
        }

        /// \brief Destroy the object LockCriticalSection and
        ///         unlock the previously locked CRITICAL_SECTION.
        ///
        ///////////////////////////////////////////////////////////
        virtual ~LockCriticalSection()
        {
            LeaveCriticalSection(m_pCriticalSection);
        }
private:
        CRITICAL_SECTION* m_pCriticalSection;
};

そしてこれはあなたの質問からの修正されたソースコードです:

do
{
    {
        LockCriticalSection lock(&criticalSectionToLock);
        while (!commandExec->commands.empty())
        {
            commandExec->ExecuteCommand(commandExec->commands.front());
            commandExec->commands.pop_front();
        }
    } // here the critical section is released
    // suspend thread here
} while (commandExec->maintainCommandExecution);
于 2012-11-08T00:10:27.037 に答える