空のtryブロックでtry {}最後に{}を使用するのはなぜですか?


239

System.Threading.TimerBase.Dispose()メソッドでtry{} finally{}ブロックがあることに気づきましたが、try{}は空です。

try{} finally{}空で使用する価値はありますtryか?

http://labs.developerfusion.co.uk/SourceViewer/browse.aspx?assembly=SSCLI&namespace=System.Threading&type=TimerBase

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal bool Dispose(WaitHandle notifyObject)
{
    bool status = false;
    bool bLockTaken = false;
    RuntimeHelpers.PrepareConstrainedRegions();
    try {
    }
    finally {
        do {
            if (Interlocked.CompareExchange(ref m_lock, 1, 0) == 0) {
                bLockTaken = true;
                try {
                    status = DeleteTimerNative(notifyObject.SafeWaitHandle);
                }
                finally {
                    m_lock = 0;
                }
            }
            Thread.SpinWait(1);
            // yield to processor
        }
        while (!bLockTaken);
        GC.SuppressFinalize(this);
    }

    return status;
}

System.Diagnostics.Processライン2144の周りだけでなく、:referencesource.microsoft.com/#System/services/monitoring/...
パトリックArtner

回答:


171

http://blog.somecreativity.com/2008/04/10/the-empty-try-block-mystery/から:

この方法は、Thread.Abort呼び出しが処理を中断するのを防ぎます。Thread.AbortのMSDNページには、「スレッドが中止される前に、未実行のfinallyブロックが実行される」と記載されています。したがって、誰かがスレッドでAbortを呼び出して途中で中止された場合でも処理が確実に終了するようにするには、すべてのコードをfinallyブロックに配置します(代わりに、「catch」ブロックにコードを記述して「試行」が中止によって中断される前にどこにいたかを確認し、必要に応じてそこから続行します)。


6
msdn.microsoft.com/en-us/library/…を使用しないのはなぜですか?
Rob Fonseca-Ensor 2010

15
それは.NET 2.0まで利用できなかったため
Hans Passant

6
RobFonseca-アンソール@:のでThread.BeginCriticalRegion()しません防ぐため中止さから糸を、ということをランタイム伝えた場合、スレッドが中断され、その後、グローバルな状態が破損しているが、全体のAppDomainには慈悲の殺害までです。
kkm 2014

9
@HansPassantは:BeginCriticalSection()あなたが言っていることに意味するものでは、実際には.NET 1.xのではありませんでしたが、何の原因と効果がありませんので。実際、.NET 1.xでは、finallyブロックでさえスレッドの中止によって中断された可能性があります。これらのメカニズムは別の目的で機能します。グローバルな状態が危険にさらされていることをランタイムに宣言するだけfinallyで、コードの途中で中止されるのを防ぎBeginCriticalSection()ます。
kkm 2014

開発者が最終的にwhile(true)を持っている場合、アボートはこれまでに完了しますか、または技術的にアボートを無期限に無視できますか?
Max Young

64

これはThread.Abort、プロセスの中断を防ぐためです。このメソッドのドキュメントには、次のように記載されています。

未実行のfinallyブロックは、スレッドが中止される前に実行されます。

これは、エラーから正常に回復するために、コード自体をクリーンアップする必要があるためです。C#は持っていないので、C ++ -スタイルデストラクタ、finallyおよびusingブロックは、そのようなクリーンアップが確実に行われることを保証する唯一の信頼できる方法です。usingコンパイラによってブロックがこれに変わることを覚えておいてください:

try {
    ...
}
finally {
    if(obj != null)
        ((IDisposable)obj).Dispose();
}

.NET 1.xでは、finallyブロックが中止される可能性がありました。この動作は.NET 2.0で変更されました。

さらに、空のtryブロックがコンパイラーによって最適化されることはありません。


使用ブロックに関する洞察をありがとう。
ステファン

@Anton使用することがベストプラクティスであることを理解しています。ただし、モックを作成するために、ラッパークラスを実装する必要があり、使い捨てオブジェクトがプライベートクラス変数になる場合があります。このラッパーを使い捨てにする場合、GCはプライベートクラス変数の破棄を自動的に処理しませんか?
Ozkan 2018

@Ozkan GCは何も自動的に破棄しません。通常はを呼び出して、ファイナライザを実装する必要がありDispose(false);ます。docs.microsoft.com/en-us/dotnet/standard/garbage-collection/…–
Thorarin

@Thorarin申し訳ありませんが、GCは自動的に破棄(ファイナライズ)しないと言っています。
Ozkan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.