2

我的同事在下面写了这段代码“closeConnection()”,它抛出了一个类型的异常:

检测到 RaceOnRCWCleanup

已尝试释放正在使用的 RCW。RCW 正在活动线程或其他线程上使用。尝试释放正在使用的 RCW 可能会导致损坏或数据丢失。

private static void closeConnection()
    {
        if(connection != null)
        {
            try
            {
                connection.Close(); // <-- this is the problem
            }
            catch(Exception)
            {
            }

            connection = null;
        }
    }

由于此代码包含在 try { } catch { } 块中,因此我得出结论,您无法捕获此类异常。是这样吗?

4

2 回答 2

7

这不是一个例外,它是一个调试器警告。它是“托管调试助手”之一,旨在捕获可能导致以后很难诊断问题的常见错误。所以不,你不能用 try/catch 来捕捉它。您可以使用 Debug + Exceptions、Managed Debugging Assistants、Thrown 复选框将其关闭以用于“RaceOnRCWCleanup”。

可能是一场虚惊,但你应该对此有点担心。一般诊断是 connection.Close() 调用导致 COM 对象被释放。但它返回到由同一个 COM 对象启动的代码,通常是由于一个事件。这意味着它可能会返回到 COM 服务器内的代码,该代码是现已销毁的 COM 对象的一部分。如果这是服务器无法处理的事情,通常会发出一声巨响,通常是完全无法诊断的 AccessViolation。如果它没有爆炸并且你彻底测试了它,那么继续关闭警告。或者找到一种稍后调用 Close() 的方法,查看此答案以获取示例。

于 2012-12-10T18:03:59.170 回答
1

您可能有竞争条件,多个线程可以同时进入您的方法。您需要锁定,以便 2 个线程不会同时输入相同的代码,例如

public static classs SomeClass
{

private static object locker;

private static void closeConnection()
    {
        if(connection != null)
        {
            lock(locker)
            {
                if(connection != null) //might have been set to null by another thread so need to check again
                {
                    try
                    {
                        connection.Close(); // <-- this should work now
                    }
                    catch(Exception)
                    { //Don't swallow an exception here
                    }

                    connection = null;
                }
            }
       }
}

RaceOnRCWCleanup 不是异常,因此您无法捕获它,它是在 CLR 之外发生的事情,触发了调试器附件请求。

于 2012-12-10T16:48:29.950 回答