Sunday, March 29, 2009

During my presentation on Parallel Programming in .Net 4.0 at the Orlando Code Camp yesterday, I was asked a question that I didn’t know the answer to and didn’t have time in the session to try out. The question had to do with the new concurrent collections (System.Collections.Concurrent) available in .Net 4.0 and whether their concurrency also enabled us to change the collection while it was being enumerated.

We all know that this is something we can’t do:

1: var dictionary = new Dictionary<int, DateTime>();

2:

3:for (int i = 0; i < 10; i++)

4: {

5: dictionary.Add(i, DateTime.Now);

6: }

7:

8:foreach (var item in dictionary)

9: {

10: Console.WriteLine("Key: {0}", item.Key);

11: dictionary.Remove(item.Key);

12: }

13:

14: Console.WriteLine("Items remaining: {0}", dictionary.Count);

15: Console.ReadLine();

At line 11, trying to remove an item from the collection we’re enumerating over results in an InvalidOperationException -- Collection was modified; enumeration operation may not execute.

But an interesting side-effect of the concurrent collections in .Net 4.0 appears to be that this is now possible – obviously because one thread needs to be able to enumerate a concurrent collection while others are adding-to/removing-from. So changing the code to use ConcurrentDictionary:

1: var dictionary = new ConcurrentDictionary<int, DateTime>();

2:

3:for (int i = 0; i < 10; i++)

4: {

5: dictionary.TryAdd(i, DateTime.Now);

6: }

7:

8:foreach (var item in dictionary)

9: {

10: Console.WriteLine("Key: {0}", item.Key);

11: var temp = item.Value;

12: dictionary.TryRemove(item.Key, out temp);

13: }

14:

15: Console.WriteLine("Items remaining: {0}", dictionary.Count);

16: Console.ReadLine();

Results in our being able to enumerate the dictionary and remove each item as we process it.

But what if we want to remove one of the items that hasn’t been processed yet? What if some value in the current item being processed results in our needing to remove a future item?

1: var dictionary = new ConcurrentDictionary<int, DateTime>();

2:

3:for (int i = 0; i < 10; i++)

4: {

5: dictionary.TryAdd(i, DateTime.Now);

6: }

7:

8:foreach (var item in dictionary)

9: {

10: Console.WriteLine("Key: {0}", item.Key);

11:if (item.Key == 4)

12: {

13: DateTime temp = DateTime.Now;

14: dictionary.TryRemove(8, out temp);

15: }

16: }

17:

18: Console.WriteLine("Items remaining: {0}", dictionary.Count);

19: Console.ReadLine();

In this example, when we process the item with a key of 4, we want to remove key 8 from the collection – which also works:

And corollary of this is also true, that if we try to add to the collection while enumerating:

1:foreach (var item in dictionary)

2: {

3: Console.WriteLine("Key: {0}", item.Key);

4:

5:if (dictionary.Count < 20)

6: {

7: dictionary.TryAdd(dictionary.Count + 1, DateTime.Now);

8: }

9: }

It works as well:

So a special “thank you” to the gentleman in my session yesterday who asked the question. It looks like the answer’s “yes”.

Saturday, March 28, 2009

Another great day at a code camp, this time in my hometown of Orlando.

I arrived a little late, due to a night out with friends Friday, so was only able to attend a couple sessions myself before presenting my Parallel Programming in .Net 4.0 session – again scheduled for the last slot of the day. I’m not sure if there’s a message there or not.

The Orlando .Net User Group did a really good job on this event. Things were very well organized with a large number of attendees. One little thing that impressed was lunch – they had a ticket system for lunch that made things run very smoothly. I certainly appreciated the separate line for speakers. :) And it was nice to find that lunch was sandwiches from Honey Baked Ham – a nice break from pizza.

As with the South Florida Code Camp, the audience was great. There were a lot of really good questions again. What’s interesting is that I give this presentation multiple times to different audiences, but get different questions each time – that keeps things new and interesting for me too, especially when I don’t know the answer. I know I’ll get a couple blog posts out of the questions I didn’t have an immediate answer for and the couple I still don’t.

I want to say thank you to the attendees for making me feel appreciated – and special thanks to those who stopped by the podium to offer feedback after the session, I really appreciate that.

To follow up on one of the questions, I am available to Florida user groups to present this session and its follow-on, a deeper dive into TaskManager and Parallel.For. Feel free to email me at pjackson@lovethedot.net to make arrangements.

I once again ran out of time before being able to demo the VS 2010 parallel debugging tools, so I think I’ll have to drop that from code camp events – at user groups I can include it, because running 1:15 or 1:20 is okay.

Friday, March 27, 2009

The Internet, or at least portions of it, is often described as a community. A big one, spanning the globe and with a lot of those neighbors we’re just a bit concerned about … but a community none-the-less.

One of the cornerstones of community is the concept of banding together to help a neighbor in need. Whether it’s dropping off a casserole so someone doesn’t have to cook in a time of tragedy or an old-fashioned barn-raising, the act of a community reaching out to help an individual is one of the greatest goods humanity has ever created.

Part of the concept’s power is that many people can help one with very little effort – when the load is distributed across an entire community, it’s almost nothing for the individual contributors in the group, but a huge, positive impact on the receiver.

What does this have to do with .Net and programming? Nothing, really, it’s not another metaphor like my online dating post, but in the .Net blogging community, the bloggers and readers are sort of like neighbors – and one of our neighbors has a neighbor who needs some help. (Okay, that’s a bit convoluted, but you’ll get the point in a second.)

Over on the Fear and Loathing blog, Bil Simser has a post today, titled The Girl Next Door, about a neighbor and friend of his that needs a bit of help. The gist of it is that their daughter, Natalie, has been treated for a brain tumor and a result of the treatment is some physical limitations – difficulty holding a pencil, for instance.

In order to help Natalie start getting back to a typical life and start schooling again, they’d like to get her a laptop with Dragon Naturally Speaking – something that would allow her to use the computer with the physical limitations her treatment has placed on her. The family’s faced with some pretty hefty medical costs ($2400 / month), so this is not something they can readily afford … but the community can.

A large number of neighbors in our .Net community can each give a little bit and make a big difference in a little girl’s life.

It doesn’t have to be much from each member of the community and, even in these tight economic times, it doesn’t have to be that big a sacrifice. I spent $2 on a Venti black coffee this morning … I can give up my coffee tomorrow or the next few days in order to help someone, especially the friend of someone whose blog I get value from.

“SpicIE is a framework which allows you easily to extend Internet Explorer 7/8 with your own plugins. SpicIE wraps/hides the IE COM extension interfaces and makes it easy to develop browser extensions in managed programming languages.”

In my opinion, this is something long overdue. Though I really haven’t had a need to write a browser plugin for anything, my perception – based on the availability of plugins and anecdotal evidence – is that it’s far easier to do in, say, Firefox or most other browsers than it is in Internet Explorer. That being the case, when I saw spicIE today, I decided to download it and see just how much would be involved in writing my first plugin for IE.

First, I downloaded spicIE and installed it. The install gives you a spicIE program group with two sample solutions, a help file and installation/deinstallation instructions:

It also installs a Visual Studio template for spicIE projects:

The template creates a project for you, including install/deinstall batch files, a strong-naming key and a Plugin.cs file:

Plugin.cs is the starting point for your plugin and inherits from SpicIE.Host. The template apparently didn’t like my project name of LoveTheDot.PlugIn.IE and this resulted in some initial build errors:

This is listed in the known issues, which I didn’t read before starting:

“In case you're creating a new project from the SpicIE template, either in C# or VB.NET, you should be aware of a naming constraint. The project should not contain any dots or other special characters. Otherwise, there will be a problem with the defined class structure in the codefile of the plugin.”

But these are quickly cleared up and the project then builds cleanly.

The plugin created by the template does have some basic functionality, it ties in to the OnDocumentComplete event and displays a “Hello World!” messagebox:

1:public Plugin() : base()

2: {

3: HostInstance = this;

4:this.OnDocumentComplete += Plugin_OnDocumentComplete;

5: }

6:

7:void Plugin_OnDocumentComplete(object pDisp, refobject url)

8: {

9: MessageBox.Show("Hello World!");

10: }

Building the project and executing the install batch file (which requires it be run as administrator), configures the plugin and now every page that loads within IE will say hello:

So that’s a basic little plugin, but what do I want to do with it? Well, being a playful and mischievous sort of fellow, I’ve decided to hijack MSDN.

So with a little event subscription and a couple lines of code, my plugin can now redirect any arrival at a MSDN URI right back here to my little blog:

1:public Plugin() : base()

2: {

3: HostInstance = this;

4:this.OnNavigateComplete += Plugin_OnNavigateComplete;

5: }

6:

7:void Plugin_OnNavigateComplete(object pDisp, refobject URL)

8: {

9:if (URL.ToString().StartsWith("http://msdn.microsoft.com"))

10:this.Navigate("http://www.lovethedot.net");

11: }

Imagine the fun we could have just by changing those URIs to something more interesting and installing this plugin on coworkers’ machines …

Okay, so fun, but not very useful, what else can we do? Really anything we might want to. The spicIE API includes a wealth of possibilities, including access to the page’s Document model. For instance, we could get a list of all the links on a page:

1:public Plugin() : base()

2: {

3: HostInstance = this;

4:this.OnDocumentComplete += Plugin_OnDocumentComplete;

5: }

6:

7:void Plugin_OnDocumentComplete(object pDisp, refobject url)

8: {

9:foreach (var item in DocumentProperties.LinkCollection)

10: {

11: MessageBox.Show(item);

12: }

13: }

(You’ll probably want to be careful where you run this little sample, or you’ll be clicking OK a lot.)

There’s a bit more involved if you want a user-interface (say a toolbar), but not much.

First create a user control and change it to inherit from SpicIE.Controls.Toolbar and there are two properties that must be overridden:

1:publicoverridestring PluginGuid

2: {

3: get

4: {

5:return"58AE4526-9474-4a80-A0CA-45BEFF07CEC9";

6: }

7: }

8:

9:publicoverridestring PluginProgID

10: {

11: get

12: {

13:return"LoveTheDot.PlugIn.IE.Toolbar1";

14: }

15: }

And some initialization to do in the constructor:

1:public Toolbar1()

2: {

3: InitializeComponent();

4:

5:this.ToolbarName = "Love the Dot Toolbar";

6:this.ToolbarTitle = "Love the Dot";

7:

8:this.ToolbarHelpText = "This is a very important toolbar";

9:this.ToolbarStyle = ToolbarEnum.ExplorerToolbar;

10:

11:// represents the startup size of the bar

12:this.Size = new Size(20, 20);

13:// represents the sizing steps

14:this.IntegralSize = new Size(0, 0);

15:// represents the minimum size

16:this.MinSize = new Size(20, 20);

17:// represents the maximum size

18:this.MaxSize = new Size(600, 600);

19:

20:// creates a new control collection and inserts the designer-generated controls

In this case, I gave my toolbar a title and a single button, which I’ll code now just by handling the Clicked event like I would any other button:

1:privatevoid button1_Click(object sender, EventArgs e)

2: {

3: Plugin.HostInstance.Navigate("http://www.lovethedot.net");

4: }

The SpicIE.Host class, from which my Plugin descends, has a static method “HostInstance”, which gives access to the browser manipulation methods. So now clicking on the toolbar button navigates the current browser tab to http://www.lovethedot.net.

By allowing us to write Internet Explorer 7/8 browser plugins with managed code, spicIE opens a plugin development to a whole new group of developers.