O que exatamente são recursos não gerenciados?

159

Quero saber sobre recursos não gerenciados. Alguém pode me dar uma idéia básica?

Deviprasad Das
fonte
Veja também esta página, o que dá uma explicação fantástica e padrão para o uso adequado de IDisposable, e como tirar recursos não gerenciados em conta: stackoverflow.com/questions/538060/...
Kyle Baran

Respostas:

177

Recursos gerenciados basicamente significa "memória gerenciada" que é gerenciada pelo coletor de lixo. Quando você não tiver mais referências a um objeto gerenciado (que usa memória gerenciada), o coletor de lixo (eventualmente) liberará essa memória para você.

Recursos não gerenciados são tudo o que o coletor de lixo não conhece. Por exemplo:

  • Abrir arquivos
  • Conexões de rede abertas
  • Memória não gerenciada
  • No XNA: buffers de vértices, buffers de índice, texturas etc.

Normalmente, você deseja liberar esses recursos não gerenciados antes de perder todas as referências que possui para o objeto que os gerencia. Você faz isso chamando Disposeesse objeto ou (em C #) usando a usinginstrução que tratará de chamar Disposevocê.

Se você negligenciar Disposecorretamente seus recursos não gerenciados, o coletor de lixo acabará por manipulá-lo quando o objeto que contém esse recurso for coletado com lixo (isso é "finalização"). Mas como o coletor de lixo não conhece os recursos não gerenciados, não pode dizer o quanto precisa liberá-los - portanto, é possível que seu programa tenha um desempenho ruim ou fique sem recursos por completo.

Se você mesmo implementar uma classe que lida com recursos não gerenciados, é sua responsabilidade implementar Disposee Finalizecorretamente.

Andrew Russell
fonte
7
A conexão de banco de dados aberto se enquadra em qual categoria? Gerenciado / Não gerenciado?
Deviprasad Das
8
+1 Outras respostas ignoram o ponto importante que você está chamando de Dispose em um objeto gerenciado que lida internamente com a liberação do recurso não gerenciado que ele agrupa (por exemplo, identificador de arquivo, GDI + bitmap, ...) e que, se você acessar recursos não gerenciados diretamente ( PInvoke etc.) você precisa lidar com isso.
Ian
2
@ Dev: Não gerenciado - como o GC não sabe disso (supondo que você não esteja usando algum banco de dados hipotético de memória gerenciada). Mas o próprio objeto de conexão pode não conter um recurso não gerenciado. Presumivelmente, a conexão com o banco de dados usa um arquivo aberto ou uma conexão de rede em algum lugar - mas é possível que outro objeto (que não seja o objeto de conexão) esteja manipulando esse recurso não gerenciado (talvez sua biblioteca de banco de dados armazene em cache as conexões). Verifique a documentação e veja onde ela pede para ligar Disposeou usar using.
Andrew Russell
11
Eu tenho um comentário / pergunta básica sobre isso, posso relacionar um objeto como gerenciado / não gerenciado apenas pelo tipo, por exemplo, a string é gerenciada, o DataSet não é gerenciado (é por isso que possui um método Dispose ()) , As conexões com o banco de dados não são gerenciadas (porque elas foram descartadas) etc. Assim, a suposição é que, se houver um método "Dispose ()", não será gerenciada? Além disso, o que seria um objeto XmlDocument? Obrigado
ganders
15
@ ganders Essa é uma boa regra de ouro. Embora esteja ciente de que todas as instâncias da classe C # são objetos gerenciados. Se uma instância de uma classe puder conter recursos não gerenciados, essa classe deverá ser implementada IDisposable. Se uma classe que implementar IDisposable, em seguida, você deve dispor de instâncias dessa classe com usingou Dispose()quando você está feito com eles. Com base nisso, seu inverso vale: Se uma classe implementa IDisposable, provavelmente ela mantém recursos não gerenciados internamente.
21412 Andrew Russell
56

Alguns usuários classificam arquivos abertos, conexões db, memória alocada, bitmaps, fluxos de arquivos etc. entre recursos gerenciados, outros entre não gerenciados. Então, eles são gerenciados ou não gerenciados?

Minha opinião é que a resposta é mais complexa: quando você abre um arquivo no .NET, provavelmente usa alguma classe .NET integrada System.IO.File, FileStream ou algo mais. Por ser uma classe .NET normal, ela é gerenciada. Mas é um invólucro, que por dentro faz o "trabalho sujo" (se comunica com o sistema operacional usando DLLs do Win32, chamando funções de baixo nível ou até mesmo instruções de montagem) que realmente abre o arquivo. E é isso que o .NET não conhece, não gerenciado. Mas talvez você possa abrir o arquivo usando as instruções do assembler e ignorando as funções do arquivo .NET. Em seguida, o identificador e o arquivo aberto são recursos não gerenciados.

O mesmo com o banco de dados: se você usa algum assembly de banco de dados, tem classes como DbConnection etc., elas são conhecidas pelo .NET e gerenciadas. Mas eles envolvem o "trabalho sujo", que não é gerenciado (aloca memória no servidor, estabelece conexão com ele, ...). Se você não usar essa classe de invólucro e abrir algum soquete de rede sozinho e se comunicar com seu próprio banco de dados estranho usando alguns comandos, ele não será gerenciado.

Essas classes de wrapper (File, DbConnection etc.) são gerenciadas, mas por dentro usam recursos não gerenciados da mesma maneira que você, se você não usar os wrappers e fazer o "trabalho sujo" sozinho. E, portanto, esses invólucros implementam padrões de Dispose / Finalize. É responsabilidade deles permitir que o programador libere recursos não gerenciados quando o wrapper não for mais necessário e libere-os quando o wrapper for coletado de lixo. O wrapper será coletado corretamente pelo coletor de lixo, mas os recursos não gerenciados serão coletados usando o padrão Dispose / Finalize.

Se você não usar classes internas do wrapper .NET ou de terceiros e arquivos abertos por algumas instruções do assembler, etc. em sua classe, esses arquivos abertos não serão gerenciados e você DEVE implementar o padrão de disposição / finalização. Caso contrário, haverá vazamento de memória, recurso bloqueado para sempre etc., mesmo quando você não o usar mais (operação de arquivo concluída) ou mesmo após o término do aplicativo.

Mas sua responsabilidade também é ao usar esses invólucros. Para aqueles que implementam descarte / finaliza (você os reconhece, que implementam IDisposable), implemente também seu padrão de descarte / finalize e Descarte mesmo esses invólucros ou dê um sinal para liberar seus recursos não gerenciados. Caso contrário, os recursos serão liberados após um tempo indefinido, mas é fácil liberá-lo imediatamente (feche o arquivo imediatamente e não o deixe aberto e bloqueado por vários minutos / horas aleatórios). Portanto, no método Dispose da sua classe, você chama métodos Dispose de todos os seus wrappers usados.

Martas
fonte
1
Bom sobre a clareza adicionalunmanaged vs managed resources
agora quem não deve ser nomeado.
thx pela sua resposta. Em quais classes é recomendável chamar o Dispose?
BKSpurgeon
2
Isto é simples. Em cada classe que você usa, você deve verificar se implementa a interface IDisposable. Se sim, se você usar essa classe em um método (por exemplo: abrir arquivo, armazenar texto, fechar o arquivo), poderá usar esse padrão using () {}, que chama Dispose for you automaticamente. Se você usar essa classe em mais métodos (por exemplo: sua classe contém File, no construtor ele abre o arquivo, vários métodos adicionam alguns logs ...), então você deve implementar a interface IDisposable por sua classe, implementar o padrão Dispose / Finalize e descarte adequadamente o objeto dessa classe.
21716 Martas
1
"... alguma classe .NET incorporada System.IO.File, FileStream ou algo mais. Por ser uma classe .NET normal, ela é gerenciada." Com respeito, isso é errado e enganoso. Eles não são gerenciados . Se eles foram gerenciados, você poderá alocar essas classes e esperar que o coletor de lixo lide totalmente com a desalocação de todos os recursos de uma maneira determinística. No entanto, isso fará com que identificadores de arquivo e recursos não gerenciados sejam bloqueados e mantidos por muito mais tempo do que o necessário, porque o coletor de lixo não desalocará a classe e não a finalizará por um período potencialmente muito longo.
precisa saber é o seguinte
1
@AaronLS em seu comentário, você falou sobre "FileStream", referindo-o como não gerenciado, mas não é, embora internamente use recursos não gerenciados para realizar seu trabalho. No mundo gerenciado, a Microsoft ocultou muitas coisas não gerenciadas de você implementando o descarte o padrão. Código gerenciado não significa que ele não usa recursos não gerenciados. No entanto, a Microsoft fez um bom trabalho ao implementar o IDisposable nesses tipos de objetos. Isso é evidenciado pelo fato de implementar IDisposable. Em relação a essa evidência, devemos considerá-la um objeto gerenciado.
Malik Khalil
12

Recursos não gerenciados são aqueles executados fora do .NET runtime (CLR) (também conhecido como código não .NET). Por exemplo, uma chamada para uma DLL na API do Win32 ou uma chamada para uma DLL escrita em C ++.

David
fonte
6

Um "recurso não gerenciado" não é uma coisa, mas uma responsabilidade. Se um objeto possui um recurso não gerenciado, isso significa que (1) alguma entidade externa foi manipulada de uma maneira que pode causar problemas se não for limpa e (2) o objeto possui as informações necessárias para executar essa limpeza e é responsável por fazer isso.

Embora muitos tipos de recursos não gerenciados estejam fortemente associados a vários tipos de entidades do sistema operacional (arquivos, identificadores de GDI, blocos de memória alocados etc.), não existe um tipo único de entidade que seja compartilhado por todos eles além da responsabilidade de Limpar. Normalmente, se um objeto tiver a responsabilidade de executar a limpeza, ele terá um método Dispose que o instrui a realizar toda a limpeza pela qual é responsável.

Em alguns casos, os objetos permitem a possibilidade de serem abandonados sem que alguém tenha chamado Dispose primeiro. O GC permite que os objetos solicitem a notificação de que foram abandonados (chamando uma rotina chamada Finalizar), e os objetos podem usar essa notificação para realizar a limpeza.

Termos como "recurso gerenciado" e "recurso não gerenciado" são, infelizmente, usados ​​por pessoas diferentes para significar coisas diferentes; francamente, acho que é mais útil pensar em termos de objetos como não tendo nenhuma responsabilidade de limpeza, tendo uma responsabilidade de limpeza que só será resolvida se Dispose for chamado ou tendo responsabilidade de limpeza que deve ser resolvida via Dispose, mas que pode também ser atendido pela Finalize.

supercat
fonte
5

A diferença básica entre um recurso gerenciado e não gerenciado é que o coletor de lixo conhece todos os recursos gerenciados; em algum momento, o GC irá limpar toda a memória e recursos associados a um objeto gerenciado. O GC não conhece recursos não gerenciados, como arquivos, fluxo e identificadores, portanto, se você não os limpar explicitamente em seu código, você terá vazamentos de memória e recursos bloqueados.

Roubado daqui , fique à vontade para ler o post inteiro.

Marko
fonte
2

Qualquer recurso para o qual a memória está alocada no heap gerenciado .NET é um recurso gerenciado. O CLR está completamente ciente desse tipo de memória e fará de tudo para garantir que não fique órfão. Qualquer outra coisa não é gerenciada. Por exemplo, a interoperabilidade com o COM pode criar objetos no espaço de memória do processo, mas o CLR não cuidará dele. Nesse caso, o objeto gerenciado que faz chamadas através dos limites gerenciados deve ser o responsável por qualquer coisa além dele.

Soundararajan
fonte
0

Vamos primeiro entender como os programas VB6 ou C ++ (aplicativos não Dotnet) costumavam ser executados. Sabemos que os computadores compreendem apenas o código no nível da máquina. O código no nível da máquina também é chamado como código nativo ou binário. Portanto, quando executamos um programa VB6 ou C ++, o respectivo compilador de idioma compila o respectivo código fonte do idioma em código nativo, que pode ser entendido pelo sistema operacional e hardware subjacentes.

O código nativo (código não gerenciado) é específico (nativo) para o sistema operacional no qual é gerado. Se você pegar esse código nativo compilado e tentar executar em outro sistema operacional, ele falhará. Portanto, o problema com esse estilo de execução de programa é que ele não é portátil de uma plataforma para outra.

Vamos agora entender como um programa .Net é executado. Usando o dotnet, podemos criar diferentes tipos de aplicativos. Alguns dos tipos comuns de aplicativos .NET incluem Web, Windows, Console e Aplicativos Móveis. Independentemente do tipo de aplicativo, quando você executa qualquer aplicativo .NET, acontece o seguinte

  1. O aplicativo .NET é compilado na linguagem Intermediate (IL). A IL também é conhecida como linguagem intermediária comum (CIL) e linguagem intermediária da Microsoft (MSIL). Aplicativos .NET e não .NET geram um assembly. Os assemblies têm uma extensão .DLL ou .EXE. Por exemplo, se você compilar um aplicativo Windows ou console, você obtém um .EXE, onde, quando compilamos um projeto de biblioteca da Web ou de classe, obtemos um .DLL. A diferença entre um assembly .NET e NON .NET é que, o DOTNET Assembly está no formato de idioma intermediário, enquanto o assembly NON DOTNET está no formato de código nativo.

  2. Os aplicativos NÃO DOTNET podem ser executados diretamente sobre o sistema operacional, enquanto os aplicativos DOTNET são executados sobre um ambiente virtual chamado Common Language Runtime (CLR). O CLR contém um componente chamado Just In-Time Compiler (JIT), que converterá o idioma intermediário em código nativo que o sistema operacional subjacente possa entender.

Portanto, no .NET, a execução do aplicativo consiste em 2 etapas 1. O compilador de idiomas compila o código-fonte na linguagem intermediária (IL) 2. O compilador JIT no CLR converte, o IL em código nativo que pode ser executado no sistema operacional subjacente .

Como um assembly .NET está no formato Intermedaite Language e não em código nativo, os assemblies .NET são portáveis ​​para qualquer plataforma, desde que a plataforma de destino tenha o Common Language Runtime (CLR). O CLR da plataforma de destino converte a linguagem Intermedaite em código nativo que o sistema operacional subjacente pode entender. O idioma intermediário também é chamado como código gerenciado. Isso ocorre porque o CLR gerencia o código que é executado dentro dele. Por exemplo, em um programa VB6, o desenvolvedor é responsável por desalocar a memória consumida por um objeto. Se um programador esquecer de desalocar memória, é possível que seja difícil detectar exceções de memória insuficiente. Por outro lado, um programador .NET não precisa se preocupar em desalocar a memória consumida por um objeto. O gerenciamento automático de memória, também conhecido como coleta de coleta, é fornecido pelo CLR. Apart, da coleta de lixo, existem vários outros benefícios fornecidos pelo CLR, que discutiremos em uma sessão posterior. Como o CLR está gerenciando e executando a Linguagem Intermediária, também é chamado de código gerenciado.

O .NET suporta diferentes linguagens de programação como C #, VB, J # e C ++. C #, VB e J # só podem gerar código gerenciado (IL), onde o C ++ pode gerar código gerenciado (IL) e código não gerenciado (código nativo).

O código nativo não é armazenado permanentemente em nenhum lugar, depois que fechamos o programa, o código nativo é jogado foraa. Quando executamos o programa novamente, o código nativo é gerado novamente.

O programa .NET é semelhante à execução do programa java. Em java, temos códigos de byte e JVM (Java Virtual Machine), enquanto que no .NET temos Linguagem Intermediária e CLR (Common Language Runtime)

Isso é fornecido a partir deste link - Ele é um ótimo tutor. http://csharp-video-tutorials.blogspot.in/2012/07/net-program-execution-part-1.html

himanshupareek66
fonte