3

I'm pretty new to C# programming, and the concept of the GC, and its realtions to IDisposable is still a bit vague. What does calling Dispose mean in terms of the garbage collection? Specifically i wonder if the following code may fail occationally, depending on when the garbage collection kicks in. (I have not been able to make it crash during my tests).

//List<TestClass2> tc2List;
//TestClass2 invokes a thread. It implements IDisposable. 
//Its Dispose() sets a stop-condition for the thread,
//and joins the thread, awaiting it to stop. (may take 100 msek)

tc2List.RemoveAll(t =>
{
  if (String.Compare(t.Name, "Orange") == 0)
  {
    t.Dispose(); //May take up to 100 msek
    return true;
  }
  return false;
});
  • 2
    If you're pretty new to programming ignore the garbage collector. He will do the right things automatically. Use `using` for objects that contain unmanaged resources(like Connections), otherwise don't call dispose explicitely. – Tim Schmelter Jan 25 '13 at 10:16
  • `IDisposable` is only relevant when there are *unmanaged* (i.e. not memory; think OS file handles for example) resources in play. Objects that are `IDisposable` usually interact with the GC in that they arrange to get disposed automatically after their memory is reclaimed as a safety measure, but that's as far as the connection goes. GC and `IDisposable` are otherwise unrelated. – Jon Jan 25 '13 at 10:16
  • I did not mention this in my post, but the class will hold a serial port until the thread is stopped. I need to be sure that this is released. – Jan Petter Jetmundsen Jan 25 '13 at 10:26
  • 2
    @Jon: "IDisposable is only relevant when there are unmanaged (i.e. not memory; think OS file handles for example) resources in play." - not really true. It's also important when, for example, you are unhooking event handlers when a form is closed. If you do not unhook event handlers, you can get memory leaks. A reasonable solution is to use IDisposable in these cases, even though the "resources" you are freeing are not unmanaged. See for example http://stackoverflow.com/questions/452281/using-idisposable-to-unsubscribe-events (but also see http://msdn.microsoft.com/en-us/library/aa970850.aspx) – Matthew Watson Jan 25 '13 at 10:32
  • @MatthewWatson: Sure, but that was not intended to go into a technical manual; it was a short blurb specifically targeted at a complete newbie. I 'm sure you get the general idea. – Jon Jan 25 '13 at 11:14

4 Answers4

4

Your code works, but it's bad style. Predicates should not have side effects. So you should first dispose the elements, and then remove them.

Predicate<T> filter = t => t.Name == "Orange";
foreach(var t in tc2List.Where(filter))
  t.Dispose();
tc2List.RemoveAll(filter);
CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
2

i wonder if the following code may fail occationally, depending on when the garbage collection kicks in

No, it won't fail

//Its Dispose() sets a stop-condition for the thread,
//and joins the thread, awaiting it to stop. (may take 100 msek)

That is a slightly a-typical use of Dispose() but not wrong. A more efficient approach would use a different Stop() so that you can stop all threads at once. Or call Dispose() from Parallel.ForEach(). But whatever method you choose, it is not hindering, nor is it being hindered by, the GC.

H H
  • 263,252
  • 30
  • 330
  • 514
1

Do you have finalize method in you TestClass2?

Dispose main properties

  1. This has to be implemented in classes implementing IDispose interface.
  2. Its the right place for freeing-up unmanaged resources like file, handles, and connections etc.
  3. Dispose() method is called explicitely in the code itself.
  4. Dispose() method is automatically called (for objects which implement IDispose), when used in a "using"

Refer to link.

D J
  • 6,908
  • 13
  • 43
  • 75
  • No. There is no finalize method in my TestClass. Based on the comment by Henk Holterman, i realized that i did not need the Dispose either. I implemented a Stop() that stopped the thread i was using. – Jan Petter Jetmundsen Jan 25 '13 at 10:49
  • That's correct, may be you would like to go through the link (in my answer) where you can see how and why you should use dispose. – D J Jan 25 '13 at 10:54
0

What does calling Dispose mean in terms of the garbage collection?

Calling dispose, means you are forcibly cleaning up things (literally the memory) using your implementation of the Dispose method. Note : (Some of the framework classes do call your implementation of Dispose for you. System.Windows.Forms.Form for example)

Garbage collection on the contrast is a feature of the .NET runtime that will clean up things for you automatically. Automatically i mean, because its up to the memory pressure and other factors that is taken care by the runtime.

A simple strategy i would recommend. Do Dispose() if you think that the memory would stay longer than needed and would impact the application. Else leave it to the runtime, it will automatically cleans up (i.e finalizes) the objects when they go out of scope. The GC has its own algorithm on how to do cleanup, but you can to a greater extent rely on it.

The next question Specifically i wonder if the following code may fail occasionally, depending on when the garbage collection kicks in

I guess no. Failure of the code due to GC kicking in, depends on how you write the finalizer of TestClass2. Definitely your call t.Dispose() wont clash with the GC.

Soundararajan
  • 2,000
  • 21
  • 23
  • _cleaning up things (literally the memory)_ - No, Dispose does not clean/release/collect memory that at all. – H H Jan 25 '13 at 11:57
  • Dispose is semantically suppose to do that, if i understand correctly. – Soundararajan Jan 25 '13 at 12:48
  • 1
    Dispose is designed to clean up only unmanaged resources (like closing handlers, cleaning unmanaged memory etc.). No managed memory cleaning. So saying that Dispose cleans memory is very wrong – Archeg Jan 25 '13 at 14:40