8

From this thread, Dispose() must be explicitly called for disposable objects.

What happens when a Windows Service stops? Are the resources used by these objects automatically freed? Or should they be disposed before the service stops like this:

public void Stop()
{
    cancellationTokenSource.Cancel();
    waitForAllTasksToExit();
    cancellationTokenSource.Dispose();
}

"It's a good practice to dispose", "They should be freed when the service stops" is what I think too. But is there a concrete answer with reference to the documentation?

Xpleria
  • 5,472
  • 5
  • 52
  • 66
  • 3
    AFAIK, when a program ends all of its memory is released. Are you experiencing something different? – Camilo Terevinto Oct 10 '17 at 12:46
  • 2
    @CamiloTerevinto it's not just about memory - open (database) connections, file access and so on is handled within a `Dispose` aswell – Toshi Oct 10 '17 at 12:47
  • @CamiloTerevinto Well, there isn't a problem now. But the question is, what is the right method? Should it be done explicitly? Does the documentation say this? – Xpleria Oct 10 '17 at 12:50
  • FYI (not an answer) but a `using` block will automatically call `Dispose()` – BurnsBA Oct 10 '17 at 12:51
  • Your example is a special case, I think: https://blog.stephencleary.com/2013/03/async-oop-6-disposal.html – Fildor Oct 10 '17 at 12:54
  • 2
    All resources "local" to your process (memory, windows handles, and so on) will be automatically freed. But its's a good practice to dispose anyway all objects: as @Toshi says, you have to consider objects that are somehow external to you process. e.g, a database server will consider a not disposed connection as still active (and eventually will free it using its own way to detect that connection is not active any more) – Gian Paolo Oct 10 '17 at 12:55
  • [Related question](https://stackoverflow.com/q/34464229/4593390) – Yoh Deadfall Oct 10 '17 at 14:24
  • @YohDeadfall The question refers to unexpected termination. But I'm asking about the `Stop()` method of a service called when stopping the service. – Xpleria Oct 10 '17 at 14:31
  • @NeilPatrao Yes, but the answers say what would be with resources which aren't disposed. And that's exactly what is you asked. – Yoh Deadfall Oct 10 '17 at 14:41

3 Answers3

5

It depends on what are "resources used by these objects". Dispose method itself won't be called on process exit, but most objects that contain "unmanaged" resources in addition to Dispose also have finalizer. Finalizer will be called on process exit, but it might not be called on process crash. Now, on process exit (or crash) the following happens:

Any resources allocated by the process are freed.

All kernel objects are closed.

Kernel objects are for example file handles, sockets and so on. So even if process crashed and finalizers are not run (or there was no finalizer at all) - things like files or database\network connections will still be closed by OS.

You might have broader definition of unmanaged resource. Unmanaged means not managed by .NET Framework garbage collector. If I for example create a file on disk when creating some object and going to delete this file when this object is disposed - you might say this is also "unmanaged" resource. Such resource is not known to OS and it will not be "cleaned" if I've not implemented finalizer or finalizer was not called because of process crash.

All in all - if object implements IDisposable- dispose it even before process exit. You might not know the intentions of that object developer, whether it has a finalizer or not - so it's better to always explicitly dispose it even before process exit.

Community
  • 1
  • 1
Evk
  • 98,527
  • 8
  • 141
  • 191
2

@Evk already gave an answer, but it wasn't completely clear for me. After an extensive search through the documentation, I've compiled the following answer with reference to the documentation.

Long Answer:

When a Service stops, it's resources will be freed by the Garbage collector.

So what about the objects that implement IDisposable? Will the unmanaged resources be freed? No. From Dispose Pattern:

The GC was specifically not designed to manage such unmanaged resources, which means that the responsibility for managing unmanaged resources lies in the hands of the developers.

So, what happens to the unmanaged resources? Are they never going to be freed?

There's still a chance

Object declares a virtual method Finalize (also called the finalizer) that is called by the GC before the object’s memory is reclaimed by the GC and can be overridden to release unmanaged resources.

This however has some drawbacks:

  1. The finalizer of an object is called after some undetermined period of time after the GC detects that it is eligible for collection.
  2. The finalizers are run between collections and so the object's memory is not released until the next round of garbage collection.

Although the documentation says that objects implementing IDisposable.Dispose should either override the Finalize method or wrap the managed object in a SafeHandle so that if the consumer forgets to call Dispose, the unmanaged resources are still freed; we could still end up in trouble.

From the Docs, the Finalize method is called only if the derived type overrides it.

So, what if the developer has implemented neither of the 2 (Finalize or SafeHandle) above? Then we have a problem, there's no one to free the unmanged resources (at least the documentation doesn't say).

TLDR

The resources may or may not be freed (depending on circumstances explained above). So dispose all disposable objects (that are not disposed yet) in the Stop method of your service.

Xpleria
  • 5,472
  • 5
  • 52
  • 66
0

As a best practice Dispose() must be called explicitly on a disposable resource. But when you stop a windows service it sends a control message to all underlying process (that's your .NET code) and stops or unloads all AppDomain. Thus all used resources and memory should get freed up essentially

Rahul
  • 76,197
  • 13
  • 71
  • 125
  • 4
    What about unmanaged resources that only get released upon caling `Dispose`? – Uwe Keim Oct 10 '17 at 12:52
  • 1
    @UweKeim Doesn't that get triggered as well? – Camilo Terevinto Oct 10 '17 at 12:52
  • Where does the documentation say this about disposable objects? @CamiloTerevinto Dispose is not automatically called. – Xpleria Oct 10 '17 at 12:53
  • @UweKeim, even for unmanaged resource when the referencing process itself completes ... OS will clear that up. Isn't it? – Rahul Oct 10 '17 at 12:54
  • 1
    @Rahul unmanaged resources which have not been disposed will be freed when you restart your OS – Toshi Oct 10 '17 at 12:57
  • @UweKeim, might want to check https://stackoverflow.com/questions/2213627/when-you-exit-a-c-application-is-the-malloc-ed-memory-automatically-freed – Rahul Oct 10 '17 at 12:58
  • @Toshi, no need of restarting OS ... see https://stackoverflow.com/questions/2213627/when-you-exit-a-c-application-is-the-malloc-ed-memory-automatically-freed – Rahul Oct 10 '17 at 12:59
  • 2
    @Rahul: unmanaged resources are not only memory but can be database connections, file streams, network connections. They won't be released then and maybe wil lock the file or cause issues with the database or network. Suggesting to restart your OS sounds weird. Some server run for years without restart, that should not be recommended as an alternative to proper dispose pattern. – Tim Schmelter Oct 10 '17 at 13:00
  • @TimSchmelter, yes it may but logically OS should free up the resource as well since referencing process itself doesn't exists anymore. see https://stackoverflow.com/questions/2213627/when-you-exit-a-c-application-is-the-malloc-ed-memory-automatically-freed – Rahul Oct 10 '17 at 13:03
  • 1
    @Rahul: you show a C question with a very specific case and OP asked if that causes a memory leak(note that you can't compare C with C#), why do you think that this is the same with every other unmanaged resource? – Tim Schmelter Oct 10 '17 at 13:04
  • @TimSchmelter, since we are talking about unmanaged resource/memory ... moreover am not suggesting an alternative to Dispose() but saying that yes the memory/resource will get freed up once service stops successfully – Rahul Oct 10 '17 at 13:05