Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.

Channels ▼

Open Source

Sweetening the Plain Vanilla .NET FileSystemWatcher

What's Up With the dispose Method?

In .NET there is an interface IDisposabledispose method when you're done with the object.

In the case of the FileSystemWatcher, this is important because this class uses what is called "unmanaged resources". These are resources that are beyond the control of the CLR and its garbage collector so it's very difficult for the CLR to clean up these resources. When you leave this program running for a sufficient amount of time to watch a folder that has a sufficient amount of files, you will have all these file handles lying around to objects that may or may not still exist on the disk.

When you're using events, it might also be a good idea to detach those in the dispose method. Not detaching event handlers in applications that run for longer periods of time is one of the most common sources of memory leaks in services.

Neglecting to use the dispose method can be seen as the equivalent of borrowing someone's car and returning it dirty with an empty gas tank. The CLR and its GC perceive this is anywhere from mildly annoying (memory leaks) to thoroughly aggravating. It may also cause your program to stop working correctly.

Now that we've now gotten all the bits and pieces together for our file system watcher DSL, I'm curious to find out if it actually works. Listing 10 shows the code for a very small test program that takes two commands. The first one is hit, which will create a file in the folder tmp. The other one is exit, which quits the application.

require 'lib/fs_watcher'

watchers = filesystem do
  watch(File.expand_path(File.join(File.dirname(__FILE__), "tmp"))) do    #A
    on_change { |args| puts "changed #{args.full_path}" }

fpath = File.expand_path(File.join(File.dirname(__FILE__), "tmp", Time.now.strftime("%Y%m%d%H%M%s")))
puts fpath
while cmd = gets.chomp
  exit(0) if cmd == "exit"
  open(fpath, 'w'){ |f| f.puts '"Mr. Worf, scan that ship." "Aye Captain. 300 dpi?"' } if cmd == "hit"

#A Defining file watch

Listing 10: Testing the DSL

This little program has a quirk in Mono because it doesn't show the characters I type on Mac. On Windows, it shows fine and it might already be fixed in Mono by the time you read this. So the output I see is:

[email protected]:~/projects/ironruby-in-action/Samples/fs_watcher
(master)» ir test.rb 
changed /ironruby-in-action/Samples/fs_watcher/tmp/200911271311s
changed /ironruby-in-action/Samples/fs_watcher/tmp/200911271311s
changed /ironruby-in-action/Samples/fs_watcher/tmp/200911271311s

This shows the event handlers being raised all three times I typed the hit command.


In this article, we looked at building a DSL to improve the behavior of the .NET FileSystemWatcher. We've seen how we can leverage various metaprogramming techniques to manipulate objects and how we can use the flexibility of the Ruby language to build a proper DSL for watching the file system for changes. The key takeaway here is that with a little effort you can make most of the less friendly APIs in .NET easier by giving them some Ruby attention.

Related Reading

More Insights

Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.