Do we have Unmanaged resources in C#?
Asked Answered
U

7

8

I had a discussion with my friend about managed and unmanaged resources in c#.

According to my friend:

1.a) Every object in C# is managed and there is nothing like unmanaged object or resource when we code in C#. Unmanaged resource concept comes only with C++.

1.b) Whether we have managed or unmanaged resource in C++ we need to free it explicitly. Since we have automatic garbage collector in C# we need need not think about managing resources.

According to me:

2.a)If we do not have unmanaged resource then why do we need a finalizer or Dispose method in C#?

2.b)Garbage collector only has information about allocated memory and not about the state of the resources. Therefore we need to use dispose method to release resources in C#.

I need help in understanding which of the above arguments are correct and information about unmanaged resource in c#, whether they exist or not?

Thanks in Advance.

Unshaped answered 17/6, 2011 at 8:37 Comment(1)
Have you got the answer? If yes, mark it as answer.Suavity
S
10

No, it is impossible to write a C# program without using unmanaged resources. It is inevitable, a C# program runs on an operating system that is 100% unmanaged. If you use a file then you use an operating system resource. A network connection. A thread. The console. Etcetera, all very much unmanaged resources.

That fact is however hidden pretty well in .NET. The framework library has nice wrapper classes for these native objects. FileStream, Socket, Thread, Console, etcetera. Memory is an operating system resource too, the garbage collector is a wrapper around it.

Of all of these resources, only the memory resource is truly automatically managed. The rest of them get some measure of help by virtue of their wrapper class. Their finalizer is the key, it releases the operating system resource when it is called. That's pretty close to automatic, the garbage collector notices that the wrapper class object is no longer referenced anywhere so it releases it, the finalizer then ensures that the unmanaged resource is released as well.

That usually works well, you can often ignore these implementation details in your code. Many programmers do.

There is a problem with finalizers though, they take a while to start running. It takes a garbage collection to get them started, that can take anywhere from a handful of milliseconds to minutes. It is unpredictable, it depends on the rate in which you consume memory in your code. If you don't use a lot of it then it will take a long time.

You cannot always afford to wait that long for an unmanaged resource to get released. A file is a good example. When you open one to read data from the file then you really should close the file when you're done reading. If you wait until the finalizer gets that job done then you run the risk of your program failing when it needs to open the file again, some time later. You might have locked yourself out by opening the file with FileShare.None, it locks your own code out as well. No big deal: you call Close() to close the file when you're done reading. To be sure it gets closed, you should put the Close() call in a finally block so it runs even if the code aborts due to an exception. In effect, you run the finalizer code explicitly.

A more serious case is an operating system resource that is very expensive. Good examples of those are bitmaps, they can take a lot of unmanaged memory, or database connections, there is a pool for them that by default only contains 100 of them. For these, you can get yourself well into a situation where letting the finalizer take care of releasing the resource just doesn't work because it takes too long. Your program dies on an exception before the finalizer can run. Usually pretty hard to diagnose because that tends to only happens when your program is under load. Always hard to debug problems that occur when lots of things are going on, on a machine that is not on your desktop.

The .NET designers recognized this need and designed the IDisposable interface. Its Dispose() method was designed to run the code that normally is run by the finalizer, giving you a way to explicitly releasing a resource rather than waiting for the garbage collector to get around to it. And the language designers jumped on that bandwagon by adding the using keyword to their language, ensuring that IDisposable.Dispose() is automatically called.

Using using or Dispose() in your code for any object that implements IDisposable is optional, as explained above, but considered vital by many .NET programmers. Mostly because everybody started .NET programming without it and ran into a problem sooner or later when their programs got big. It is even prescribed on classes where calling Dispose() makes no sense, like MemoryStream. And causes mental anguish when a class should implement IDisposable but doesn't, like Thread. Or when a class implements both Dispose and Close (it makes no difference). For comparison, Java has the same considerations but doesn't have IDisposable.

Stope answered 17/6, 2011 at 11:54 Comment(1)
To extrapolate your answer, MemoryStream does not need but inherits IDisposable from Stream. In that case a better inheritance tree would be to have a class ManagedStream that serves as a base class for MemoryStream etc. and Stream (that would extend with IDisposable) to serve as a base-class for streams with unmanaged resources.Stephniestepladder
D
3

Objects created in .NET are managed code but your objects can hold a reference to unmanaged ressources. Garbage collector (GC) makes sure any memory allocated on the managed heap is cleaned up after it is no longer needed. However, while the garbage collector is great at making sure that memory does not leak, it doesn’t have any knowledge about other resources that need to be freed. For instance, the garbage collector doesn’t know how to close a file handle or how to release memory allocated outside of the managed heap with an API such as CoAllocTaskMem.

Objects that manage these types of resources must ensure that they are released when they’re no longer needed. You can accomplish this by overriding the Finalize method of System.Object, which lets the garbage collector know that the object would like to participate in its own cleanup (in C# you use the C++ destructor syntax, ~MyObject, rather than directly overriding the method). If a class has a finalizer, then before objects of that type are collected the garbage collector will call the object’s finalizer and allow it to clean up any resources that it may be holding onto.

One problem with this system is that the garbage collector does not run deterministically and, as a result, your object may not be finalized for a long time after the last reference to it has gone away. If your object holds onto an expensive or rare resource, such as a database connection, this may not be acceptable. For instance, if your object has 1 of only 10 available connections open, it should release that connection as soon as possible, rather than waiting for the garbage collector to call the finalize method.

For that you have a IDisposable interface that you should implement. Read more about it.

Duax answered 17/6, 2011 at 8:42 Comment(0)
A
3

a) Every object in C# is managed and there is nothing like unmanaged object or resource when we code in C#. Unmanaged resource concept comes only with C++.

This is incorrect. We can have unmanaged resources from from outside C# (e.g. COM), as others have mentioned.

However, it is certainly possible to have "unmanaged resources" in C# without accessing unmanaged code. These resources may not be unmanaged in the strict sense of garbage collection, but they are resources that you, as the developer, must handle cleaning up. Take a thread for example:

class Foo
{
    private Thread thread = new Thread(new ThreadStart(DoLotsOfWork));
    private AutoResetEvent endThread = new AutoResetEvent(false);
    private int sum = 0;

    public Foo()
    {
        thread.Start();
    }

    public StopThread()
    {
        endThread.Set();
    }

    private void DoLotsOfWork()
    {
        while (!endThread.WaitOne(1000))
        {
            sum += 1;
        }
    }
}

static void Main(string[] args)
{
    Foo foo = new Foo();
    // Additional code...
    foo.StopThread();
}

Suppose the additional code returns or throws an exception. If you do not explicitly call StopThread, the thread executing DoLotsOfWork will not end, and your process will likely not exit.

b) Whether we have managed or unmanaged resource in C++ we need to free it explicitly. Since we have automatic garbage collector in C# we need need not think about managing resources.

We absolutely must consider managing resources in C#. This is why IDisposable exists, as you suggest.

Consider this modification to the above code:

class Foo : IDisposable
{
    private bool disposed = false;
    private Thread thread = new Thread(new ThreadStart(DoLotsOfWork));
    private AutoResetEvent endThread = new AutoResetEvent(false);
    private int sum = 0;

    public Foo()
    {
        thread.Start();
    }

    public StopThread()
    {
        endThread.Set();
    }

    public Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void DoLotsOfWork()
    {
        while (!endThread.WaitOne(1000))
        {
            sum += 1;
        }
    }

    private void Dispose(bool disposing)
    {
        if (!disposed && disposing)
        {
            StopThread();
            disposed = true;
        }
    }
}

static void Main(string[] args)
{
    using (Foo foo = new Foo())
    {
        // Additional code...
    }
}

Now we can be sure that no matter what the additional code does, the thread created by the Foo class will be stopped before the process exits.

Acuminate answered 17/6, 2011 at 11:25 Comment(0)
M
2

Every thing you create under the .net Framework is Mananged code and so the memeory consume by the object created by using .net framework manager by framework only.

Every thing which get created outside the .net framwork is unmanaged code.

You can use finalizer or dispose when you want to relase the hevy object like you need to close the files or you are usning graphics and you want to release memory associated with it you can use this methods.

Meadowsweet answered 17/6, 2011 at 8:43 Comment(1)
The concepts of managed and unmanaged code are largely orthogonal to the concepts of managed and unmanaged resources. A managed resource is an object which should be cleaned up manually, but will eventually (via Finalize) perform necessary cleanups if it is abandoned. An unmanaged resource is an entity (which can be just about anything) that requires some form of manual cleanup that will not happen if it is simply abandoned. While one cannot have managed resources except in managed code, unmanaged resources can exist anywhere even within 100% managed code.Kowloon
S
1

It is true that all objects created in the CLR are managed by the CLR, so you don't need to care about them.

However when you start using resources external to the CLR (a COM object for example, or a lock on a device) it is your responsibility to free those resources. The CLR cannot do it for you, but provides the IDisposable interface to let you write code that does the cleanup.

Screwy answered 17/6, 2011 at 8:44 Comment(0)
M
1

We do have to deal with unmanaged resourses in .NET. A good example, is a connection to a database.

We have to explicitly close that unmanaged resource. This is an example of why we have Dispose in C#.

Moorhead answered 17/6, 2011 at 8:45 Comment(0)
K
1

An object which holds unmanaged resources puts other entities into a somewhat undesirable state (e.g. making them unavailable for other purposes) until it is told that it is no longer needed. If it is abandoned without first having been told that it is no longer needed, those other entities will be left in the undesirable state.

A managed resource is an entity which similarly puts other entities into a somewhat-undesirable state until it is told it is no longer needed, but it will eventually automatically clean itself up if all "deliberate" references to it are abandoned.

Event subscriptions from long-lived objects exist entirely within managed code, but because they are not cleaned up automatically during the lifetime of the long-lived objects, they should be regarded as unmanaged resources.

Kowloon answered 17/6, 2011 at 18:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.