Ich möchte etwas über nicht verwaltete Ressourcen wissen. Kann mir bitte jemand eine Grundidee geben?
Ich möchte etwas über nicht verwaltete Ressourcen wissen. Kann mir bitte jemand eine Grundidee geben?
Antworten:
Verwaltete Ressourcen bedeuten im Grunde "verwalteten Speicher", der vom Garbage Collector verwaltet wird. Wenn Sie keine Verweise mehr auf ein verwaltetes Objekt haben (das verwalteten Speicher verwendet), gibt der Garbage Collector diesen Speicher (eventuell) für Sie frei.
Nicht verwaltete Ressourcen sind dann alles, was der Garbage Collector nicht weiß. Beispielsweise:
Normalerweise möchten Sie diese nicht verwalteten Ressourcen freigeben, bevor Sie alle Verweise auf das Objekt verlieren, das sie verwaltet. Sie tun dies, indem Sie dieses Dispose
Objekt aufrufen oder (in C #) die using
Anweisung verwenden, die den Aufruf Dispose
für Sie übernimmt .
Wenn Sie Dispose
Ihre nicht verwalteten Ressourcen korrekt vernachlässigen , wird der Garbage Collector diese möglicherweise für Sie verarbeiten, wenn das Objekt, das diese Ressource enthält, Garbage Collected ist (dies ist "Finalisierung"). Da der Garbage Collector jedoch nichts über die nicht verwalteten Ressourcen weiß, kann er nicht sagen, wie dringend er freigegeben werden muss. Daher kann es sein, dass Ihr Programm eine schlechte Leistung erbringt oder keine Ressourcen mehr zur Verfügung stehen.
Wenn Sie eine Klasse selbst implementieren , dass Griffe Ressourcen unmanaged, ist es an Ihnen, zu implementieren Dispose
und Finalize
richtig.
Dispose
oder zu verwenden using
.
IDisposable
. Wenn eine Klasse nicht implementieren IDisposable
, dann Sie sollten von Instanzen dieser Klasse verfügen mit using
oder Dispose()
wenn Sie mit ihnen fertig sind. Auf dieser Grundlage gilt Ihre Umkehrung: Wenn eine Klasse implementiert wird IDisposable
, enthält sie wahrscheinlich intern nicht verwaltete Ressourcen.
Einige Benutzer zählen offene Dateien, Datenbankverbindungen, zugewiesenen Speicher, Bitmaps, Dateistreams usw. zu den verwalteten Ressourcen, andere zu den nicht verwalteten. Werden sie also verwaltet oder nicht verwaltet?
Meiner Meinung nach ist die Antwort komplexer: Wenn Sie eine Datei in .NET öffnen, verwenden Sie wahrscheinlich eine integrierte .NET-Klasse System.IO.File, FileStream oder etwas anderes. Da es sich um eine normale .NET-Klasse handelt, wird sie verwaltet. Aber es ist ein Wrapper, der die "Drecksarbeit" erledigt (kommuniziert mit dem Betriebssystem über Win32-DLLs, ruft Funktionen auf niedriger Ebene oder sogar Assembler-Anweisungen auf), die die Datei wirklich öffnen. Und das ist, was .NET nicht weiß, nicht verwaltet. Sie können die Datei jedoch möglicherweise selbst öffnen, indem Sie Assembler-Anweisungen verwenden und die Funktionen der .NET-Datei umgehen. Dann sind das Handle und die geöffnete Datei nicht verwaltete Ressourcen.
Das Gleiche gilt für die Datenbank: Wenn Sie eine DB-Assembly verwenden, haben Sie Klassen wie DbConnection usw., die .NET bekannt sind und verwaltet werden. Aber sie verpacken die "schmutzige Arbeit", die nicht verwaltet wird (Speicher auf dem Server zuweisen, Verbindung herstellen, ...). Wenn Sie diese Wrapper-Klasse nicht verwenden und selbst einen Netzwerk-Socket öffnen und mit einigen Befehlen mit Ihrer eigenen seltsamen Datenbank kommunizieren, wird diese nicht verwaltet.
Diese Wrapper-Klassen (Datei, DbConnection usw.) werden verwaltet, verwenden jedoch nicht verwaltete Ressourcen auf dieselbe Weise wie Sie, wenn Sie die Wrapper nicht verwenden und die "Drecksarbeit" selbst ausführen. Und deshalb implementieren diese Wrapper Dispose / Finalize-Muster. Es liegt in ihrer Verantwortung, dem Programmierer zu ermöglichen, nicht verwaltete Ressourcen freizugeben, wenn der Wrapper nicht mehr benötigt wird, und sie freizugeben, wenn der Wrapper durch Müll gesammelt wird. Der Wrapper wird korrekt vom Garbage Collector gesammelt, aber die nicht verwalteten Ressourcen im Inneren werden mithilfe des Dispose / Finalize-Musters gesammelt.
Wenn Sie in Ihrer Klasse keine integrierten .NET- oder Drittanbieter-Wrapper-Klassen verwenden und Dateien nicht durch Assembler-Anweisungen usw. öffnen, werden diese geöffneten Dateien nicht verwaltet und Sie MÜSSEN das Dispose / Finalize-Muster implementieren. Wenn Sie dies nicht tun, kommt es zu einem Speicherverlust, einer für immer gesperrten Ressource usw., selbst wenn Sie diese nicht mehr verwenden (Dateivorgang abgeschlossen) oder sogar nachdem Ihre Anwendung beendet wurde.
Ihre Verantwortung liegt jedoch auch bei der Verwendung dieser Wrapper. Für diejenigen, die dispose / finalize implementieren (Sie erkennen, dass sie IDisposable implementieren), implementieren Sie auch Ihr dispose / finalize-Muster und entsorgen Sie sogar diese Wrapper oder geben Sie ihnen das Signal, ihre nicht verwalteten Ressourcen freizugeben. Wenn Sie dies nicht tun, werden die Ressourcen nach einer unbestimmten Zeit freigegeben, aber es ist sauber, sie sofort freizugeben (schließen Sie die Datei sofort und lassen Sie sie nicht offen und blockieren Sie sie zufällig für einige Minuten / Stunden). In der Dispose-Methode Ihrer Klasse rufen Sie also Dispose-Methoden aller verwendeten Wrapper auf.
unmanaged vs managed resources
Eine "nicht verwaltete Ressource" ist keine Sache, sondern eine Verantwortung. Wenn ein Objekt eine nicht verwaltete Ressource besitzt, bedeutet dies, dass (1) eine Entität außerhalb der Ressource auf eine Weise manipuliert wurde, die Probleme verursachen kann, wenn sie nicht bereinigt wird, und (2) das Objekt über die für die Durchführung einer solchen Bereinigung erforderlichen Informationen verfügt und dafür verantwortlich ist dafür.
Obwohl viele Arten von nicht verwalteten Ressourcen sehr stark mit verschiedenen Arten von Betriebssystementitäten (Dateien, GDI-Handles, zugewiesene Speicherblöcke usw.) verbunden sind, gibt es keinen einzigen Entitätstyp, der von allen gemeinsam genutzt wird, außer der Verantwortung von Aufräumen. Wenn ein Objekt entweder für die Durchführung der Bereinigung verantwortlich ist, verfügt es normalerweise über eine Dispose-Methode, die es anweist, alle Bereinigungen durchzuführen, für die es verantwortlich ist.
In einigen Fällen berücksichtigen Objekte die Möglichkeit, dass sie verlassen werden, ohne dass zuvor jemand Dispose angerufen hat. Mit dem GC können Objekte eine Benachrichtigung anfordern, dass sie abgebrochen wurden (durch Aufrufen einer Routine namens Finalize), und Objekte können diese Benachrichtigung verwenden, um selbst eine Bereinigung durchzuführen.
Begriffe wie "verwaltete Ressource" und "nicht verwaltete Ressource" werden leider von verschiedenen Personen verwendet, um unterschiedliche Bedeutungen zu haben. Ehrlich gesagt ist es sinnvoller, in Bezug auf Objekte zu denken, dass sie entweder keine Bereinigungsverantwortung haben, eine Bereinigungsverantwortung haben, die nur dann erledigt wird, wenn Dispose aufgerufen wird, oder eine Bereinigungsverantwortung haben, die über Dispose erledigt werden sollte, aber kann wird auch von Finalize erledigt.
Der grundlegende Unterschied zwischen einer verwalteten und einer nicht verwalteten Ressource besteht darin, dass der Garbage Collector alle verwalteten Ressourcen kennt. Zu einem bestimmten Zeitpunkt wird der GC den gesamten Speicher und die Ressourcen bereinigen, die einem verwalteten Objekt zugeordnet sind. Der GC kennt nicht verwaltete Ressourcen wie Dateien, Streams und Handles nicht. Wenn Sie sie also nicht explizit in Ihrem Code bereinigen, treten Speicherlecks und gesperrte Ressourcen auf.
Von hier gestohlen , können Sie den gesamten Beitrag lesen.
Jede Ressource, für die Speicher im verwalteten .NET-Heap zugewiesen ist, ist eine verwaltete Ressource. CLR ist sich dieser Art von Speicher voll bewusst und wird alles tun, um sicherzustellen, dass er nicht verwaist ist. Alles andere wird nicht verwaltet. Wenn Sie beispielsweise mit COM interoperieren, werden möglicherweise Objekte im Prozessspeicherbereich erstellt, CLR kümmert sich jedoch nicht darum. In diesem Fall sollte das verwaltete Objekt, das Anrufe über die verwaltete Grenze tätigt, die Verantwortung für alles darüber hinaus tragen.
Lassen Sie uns zunächst verstehen, wie VB6- oder C ++ - Programme (Nicht-Dotnet-Anwendungen) ausgeführt wurden. Wir wissen, dass Computer nur Code auf Maschinenebene verstehen. Code auf Maschinenebene wird auch als nativer oder binärer Code bezeichnet. Wenn wir also ein VB6- oder C ++ - Programm ausführen, kompiliert der jeweilige Sprachcompiler den jeweiligen Sprachquellcode in nativen Code, der dann vom zugrunde liegenden Betriebssystem und der zugrunde liegenden Hardware verstanden werden kann.
Der native Code (nicht verwalteter Code) ist spezifisch (nativ) für das Betriebssystem, auf dem er generiert wird. Wenn Sie diesen kompilierten nativen Code verwenden und versuchen, ihn auf einem anderen Betriebssystem auszuführen, schlägt er fehl. Das Problem bei dieser Art der Programmausführung ist also, dass sie nicht von einer Plattform auf eine andere Plattform portierbar ist.
Lassen Sie uns nun verstehen, wie ein .Net-Programm ausgeführt wird. Mit dotnet können wir verschiedene Arten von Anwendungen erstellen. Einige der gängigen Arten von .NET-Anwendungen sind Web-, Windows-, Konsolen- und Mobilanwendungen. Unabhängig vom Typ der Anwendung geschieht Folgendes, wenn Sie eine .NET-Anwendung ausführen
Die .NET-Anwendung wird in Intermediate Language (IL) kompiliert. IL wird auch als Common Intermediate Language (CIL) und Microsoft Intermediate Language (MSIL) bezeichnet. Sowohl .NET- als auch Nicht-.NET-Anwendungen generieren eine Assembly. Baugruppen haben die Erweiterung .DLL oder .EXE. Wenn Sie beispielsweise eine Windows- oder Konsolenanwendung kompilieren, erhalten Sie eine EXE-Datei. Wenn Sie ein Web- oder Klassenbibliotheksprojekt kompilieren, erhalten Sie eine DLL. Der Unterschied zwischen einer .NET- und einer NON .NET-Assembly besteht darin, dass die DOTNET-Assembly im Zwischensprachenformat vorliegt, während die NON DOTNET-Assembly im nativen Codeformat vorliegt.
NICHT-DOTNET-Anwendungen können direkt auf dem Betriebssystem ausgeführt werden, während DOTNET-Anwendungen auf einer virtuellen Umgebung ausgeführt werden, die als Common Language Runtime (CLR) bezeichnet wird. CLR enthält eine Komponente namens Just In-Time Compiler (JIT), die die Intermediate-Sprache in nativen Code konvertiert, den das zugrunde liegende Betriebssystem verstehen kann.
In .NET besteht die Anwendungsausführung aus zwei Schritten: 1. Der Sprachcompiler kompiliert den Quellcode in Intermediate Language (IL). 2. Der JIT-Compiler in CLR konvertiert den IL in nativen Code, der dann auf dem zugrunde liegenden Betriebssystem ausgeführt werden kann .
Da eine .NET-Assembly im Intermedaite Language-Format und nicht in nativem Code vorliegt, können .NET-Assemblys auf jede Plattform portiert werden, sofern die Zielplattform über die Common Language Runtime (CLR) verfügt. Die CLR der Zielplattform konvertiert die Intermedaite-Sprache in nativen Code, den das zugrunde liegende Betriebssystem verstehen kann. Intermediate Languge wird auch als verwalteter Code bezeichnet. Dies liegt daran, dass CLR den darin enthaltenen Code verwaltet. In einem VB6-Programm ist der Entwickler beispielsweise dafür verantwortlich, den von einem Objekt verbrauchten Speicher freizugeben. Wenn ein Programmierer vergisst, Speicher freizugeben, kann es schwierig sein, Ausnahmen für nicht genügend Speicher zu erkennen. Auf der anderen Seite muss sich ein .NET-Programmierer nicht darum kümmern, den von einem Objekt verbrauchten Speicher freizugeben. Die automatische Speicherverwaltung, auch als Grabage Collection bezeichnet, wird von CLR bereitgestellt. Ein Teil, Bei der Speicherbereinigung bietet die CLR mehrere weitere Vorteile, die wir in einer späteren Sitzung erörtern werden. Da CLR die Intermediate Language verwaltet und ausführt, wird sie auch als verwalteter Code bezeichnet.
.NET unterstützt verschiedene Programmiersprachen wie C #, VB, J # und C ++. C #, VB und J # können nur verwalteten Code (IL) generieren, während C ++ sowohl verwalteten Code (IL) als auch nicht verwalteten Code (nativen Code) generieren kann.
Der native Code wird nirgendwo dauerhaft gespeichert. Nachdem wir das Programm geschlossen haben, wird der native Code weggeworfen. Wenn wir das Programm erneut ausführen, wird der native Code erneut generiert.
Das .NET-Programm ähnelt der Ausführung von Java-Programmen. In Java haben wir Bytecodes und JVM (Java Virtual Machine), wo wir wie in .NET Intermediate Language und CLR (Common Language Runtime) verwenden.
Dies wird über diesen Link bereitgestellt - Er ist ein großartiger Tutor. http://csharp-video-tutorials.blogspot.in/2012/07/net-program-execution-part-1.html