Wednesday, August 27, 2008

Threading in IronRuby (Part 2)

In my last post I pointed out some issues with the Thread.new construct in IronRuby. One of the advantages of using IronRuby is that we have access to the .NET framework. In this post, we'll take a look at using the ThreadPool class in order to correct some of the issues that came up in the previous post.

The first issue that we saw with the Thread.new construct was that it launched the thread as soon as we declared it. When using the ThreadPool, we first declare a callback object:
require "mscorlib"
include System::Threading

callback = WaitCallback.new { puts "pool thread" }

We declare a callback in a similar manner to a Thread, by passing a block to the constructor. In this case, however, we get a WaitCallback object that we can hold on to until we are ready to execute the block. You can run the code block by queuing it up in the ThreadPool:
ThreadPool.queue_user_work_item callback

You may need to pause the main thread in order to see the line print to the console, giving us this as a full example:
require "mscorlib"
include System::Threading

callback = WaitCallback.new { puts "pool thread" }
ThreadPool.queue_user_work_item callback

Thread.sleep 100


The other issue that I mentioned concerning the Thread.new construct was that it defaulted to a foreground thread. This isn't a problem when using the ThreadPool since all ThreadPool threads are background threads.

A lot of this code is very un-Ruby-like. For instance, it would be nice to just write:
ThreadPool.queue_user_work_item { puts "pool thread" }

Hopefully future versions of IronRuby will make it easier to pass blocks in place of delegates. That would definitely make these tasks feel more like Ruby.

No comments: