Was ist die richtige Art von hinzufügen thread-Sicherheit auf ein IDisposable-Objekt?

Stellen Sie sich eine Umsetzung der IDisposable - Schnittstelle, die hat einige öffentliche Methoden.

Wenn eine Instanz dieses Typs wird von mehreren threads gemeinsam genutzt und einer der threads kann es entsorgen, was ist der beste Weg, um sicherzustellen, dass die anderen threads nicht versuchen zu arbeiten mit der Instanz nach entsorgt? In den meisten Fällen, nachdem das Objekt veräußert, dessen Methoden müssen sich dessen bewusst sein und werfen die ObjectDisposedException oder vielleicht InvalidOperationException oder zumindest informieren der aufrufende code für, etwas falsch zu machen. Brauche ich die Synchronisation für jeder Methode - vor allem rund um das prüfen, wenn es entsorgt wird? Tun alle IDisposable Implementierungen mit anderen öffentlichen Methoden brauchen werden, um thread-sicher?


Hier ist ein Beispiel:

public class DummyDisposable : IDisposable
{
    private bool _disposed = false;

    public void Dispose()
    {
        _disposed = true;
        //actual dispose logic
    }

    public void DoSomething()
    {
        //maybe synchronize around the if block?
        if (_disposed)
        {
            throw new ObjectDisposedException("The current instance has been disposed!");
        }

        //DoSomething logic
    }

    public void DoSomethingElse()
    {
         //Same sync logic as in DoSomething() again?
    }
}
  • Ich denke, Sie mischen Entsorgen vs Finalizer. Die Dokumente sind so zu erklären, das gewünschte Verhalten ganz gut:msdn.microsoft.com/de-de/library/...
  • Nein, bin ich nicht, aber da Sie erwähnt - Finalize() wird von einer separaten GC-thread soweit ich mich erinnere. Jedoch, Finalize wird aufgerufen, wenn es keine lebendig Referenz auf das Objekt, also thread-Sicherheit sollte nicht eine überlegung sein dann. In MS best practices es wird empfohlen, rufen Sie Dispose innen Abschließen, oder zumindest fast die gleiche Logik - siehe link. Dies könnte dazu führen, aufrufende thread-Sicherheit-beachten Sie code innerhalb der Finalize() Methode sowieso.
  • Ich fügte hinzu, Beispiel-Implementierung zu klären meiner Frage
  • Es sollte bis zu dem thread initialisiert ein Wegwerf-Objekt zum ausführen der cleanup, nachdem es nicht mehr benötigt wird. Warum lässt du einige andere Threads entsorgen Sie es? Sie können nur bekommen, selbst in Schwierigkeiten auf diese Weise.
  • Ich wollte einige Allgemeine Hinweise, die Materie, nicht mit einem bestimmten Beispiel. Sie haben Recht, in den meisten Fällen den thread erstellen sollte die Bereinigung seiner Ressourcen, aber dies kann nicht der Fall sein, in einigen Szenarien.
  • Manchmal ist die Letzte Nutzung eines Objekts kann auf einem anderen thread als dem die es schafft. Zum Beispiel, angenommen, man will asynchron spielen einen sound aus einer Datei, schließen der Datei, nachdem die Wiedergabe abgeschlossen ist. Der thread, der die Datei öffnet, können haben besseres zu tun, als zu warten, um den Ton zu beenden.
  • wenn kein anderer thread Los ist, die Datei zu verwenden, dann denke ich, es ist ok. Aber in diesem Fall sehe ich auf den Punkt in den Haupt-thread öffnen der gleichen Datei, entweder. Öffnen Sie es, spielen Sie es, schließen Sie es. Und dann machen Sie den gesamten Auftrag in einem anderen thread, wenn Sie wollen. Ich glaube nicht, dass ich jemals begegnet einem Szenario, wo möchte ich einige andere Threads zu entsorgen, ein Objekt instanziiert anderswo. Es bricht SRP, wenn nichts anderes.
  • Obwohl es möglich ist, widmen Sie einen thread zu einem längst Laufenden Betrieb, und haben es warten für jeden Teil der operation abgeschlossen ist, bevor Sie fortfahren, um zum nächsten Teil, eine effizientere Muster in vielen Fällen ist die Verwendung von asynchronen callbacks ausgelöst von Threadpool-threads. Nutzt man eine "vollständige Wiedergabe" Rückruf schließen Sie die audio-Datei, ist es durchaus möglich, dass die Datei könnte sich geschlossen in einem thread, die gar nicht existieren, wenn die Datei geöffnet wurde, oder, dass der thread, der die Datei geöffnet hat, könnte aufhören zu existieren, bevor die Wiedergabe beendet und die Datei geschlossen.
  • Auch, wie ich bemerkte auf einer anderen Antwort, es gibt einige Fälle, wo der natürlichste Weg zum Abbruch einer blockierenden I/O-operation ist, entsorgen Sie die Ressource aus darunter. Wenn das scheint eklig, beachten Sie, dass einige Objekte ermöglichen, dass Operationen abgebrochen werden, ohne zu stören das gesamte system Staat, sondern die Objekte, deren Operationen abgebrochen werden, werden Sie unbrauchbar. Wenn etwas zu tun auf ein Objekt, wird es nutzlos, diese Aktion kann auch über den Objekt -. Wenn ein Objekt angeordnet ist, während eine seiner Methoden ist warten, dass etwas geschieht, macht es wenig Sinn für Sie zu halten, zu warten.
  • Wenn Abbruch einer operation auf ein Objekt, wird es nutzlos, und bei der Entsorgung ein Objekt sollte dazu führen, dass ein blockierender Vorgang abgebrochen werden, dann Entsorgen Sie das Objekt scheint eine gute Möglichkeit zum Abbrechen einer operation.
  • Ich weiß, es ist ein altes Thema, aber ich habe eine Korrektur zum hinzufügen zu Ihrem Kommentar: "Finalize wird aufgerufen, wenn es keine lebendig Referenz auf das Objekt, also thread-Sicherheit sollte nicht eine überlegung sein dann." Leider, Finalizer, dass Sie müssen Sorge um die thread-Sicherheit auch wenn die Klasse ist nicht dazu gedacht, den thread-sicher auf der Außenseite. Dies ist, weil der finalizer kann ausgeführt werden, auch während eine andere Methode der Klasse wird noch ausgeführt! Weitere Informationen finden Sie unter blogs.msdn.microsoft.com/oldnewthing/20100810-00/?p=13193 und vor allem blogs.msdn.microsoft.com/oldnewthing/20100813-00/?p=13153.

Schreibe einen Kommentar