如何捕获临界区中抛出的异常?

时间:2009-03-19 17:05:07

标签: c++ multithreading winapi exception

我正在使用c ++进行win 32多线程处理。 场景: 我有一个多线程使用的函数。 此函数作为关键部分(或任何可以锁定资源的构造)。 在临界区中抛出异常。 此时我需要在异常catch块中解锁资源。

还有其他方法可以做到吗?我的意思是,让我们说我不想记得在catch块中释放锁,是否有任何常见的方法来处理这个问题以避免这种容易出错的情况?

4 个答案:

答案 0 :(得分:16)

这个想法是封装获取和释放对象中的关键部分的行为,以便构造对象获取CS并销毁对象释放它。

struct CSHolder {
    explicit CSHolder(CRITICAL_SECTION& cs): lock(cs) {
        ::EnterCriticalSection(&lock);
    }
    ~CSHolder() { ::LeaveCriticalSection(&lock); }
    CRITICAL_SECTION& lock;
};


CRITICAL_SECTION gLock;
void foo() {
    CSHolder lockIt(gLock);
    // lock is held until lockIt is destroyed
}

这个概念叫做RAII - 资源获取是初始化。这是现代C ++中非常常见的习语。

答案 1 :(得分:3)

如果您正在使用现有框架,那么您可能已经拥有可以为您执行此操作的RAII容器类。如果您使用的是MFC,请查看CSingleLock,如果您正在使用scoped_lock的加速查看。

令人遗憾的是,每个人似乎都必须(或者认为必须)自己动手。

答案 2 :(得分:2)

编写一个括号类,它将一个临界区作为构造函数参数。在构造函数中调用EnterCriticalSection,在析构函数中调用LeaveCriticalSection。如果抛出C ++异常,堆栈展开将完成剩下的工作。

答案 3 :(得分:2)

如果您可以使用MFC,则可以使用CSingleLock执行此操作。您可以像这样使用它:

void f()
{
  try
  {
    CSingleLock lock(&m_criticalSection, TRUE);

  }
  catch(/*some exception*/)
}

锁将负责解锁其析构函数中的关键部分。因为lock是抛出异常时的本地对象,所以堆栈展开并执行锁定对象析构函数来解锁你的关键部分。