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

これは例外ではなく、デバッガーの警告です。これは「マネージ デバッグ アシスタント」の 1 つで、後で問題を診断するのが非常に困難になる可能性のあるよくある間違いを検出するように設計されています。いいえ、try/catch でキャッチすることはできません。Debug + Exceptions、Managed Debugging Assistants、「RaceOnRCWCleanup」のThrownチェックボックスでオフにします。

誤報の可能性がありますが、これについては少し心配する必要があります。一般的な診断は、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 に答える