Monthly Archives: October 2010

ParallelForEach with Result .NET 3.5

In an earlier post I described how I wrote a couple extension methods to give me a reasonably safe way to iterate objects in a generic enumerable and execute actions on the items in a multithreaded way. Since writing it I’ve used the methods to great success.

I did the first implementation using actions because they have no return type. I figured delegates of this type would lend themselves very simply to a multithreaded design. Today, however, I came across a need to apply length rules to objects and receive a collection of the results (essentially those that passed the test.) I could have used a predicate over the iterated items and returned those that evaluated true but instead I went with an implementation using Func for the flexibility to return pieces of information from within the iterated objects rather than the objects themselves.

I used my previous ParallelForEach methods as a starting point. Then I replaced the Action<T> parameter with Func<T, TResult> and gave the extension method a return type of IEnumerable<TResult>. This is because I will be collecting the results from each thread and returning them.

public static IEnumerable<TResult> ParallelForEach<T, TResult>(
                                      this IEnumerable<T> enumerable,
                                      Func<T, TResult> func)
{
   return ParallelForEach(enumerable, func, enumerable.Count());
}

The method body is essentially the same as well but with the difference that I collect a result and add it into a list.

public static IEnumerable<TResult> ParallelForEach<T. TResult>(
                                      IEnumerable enumerable,
                                      Func<T, TResult> func,
                                      int count)
{
   List<TResult> results = new List<TResult>(count);

   using (var cd = new Countdown(count))
   {
      foreach (T current in enumerable)
      {
         T captured = current;
         ThreadPool.QueueUserWorkItem(x =>
         {
            TResult result = func(captured);
            results.ThreadSafeAdd(result);
            cd.Signal();
         });
      }
   }

   return results;
}

To keep the list object from getting accessed by multiple threads I added an extension method to do a thread safe add using the list’s SyncRoot object. I only bothered implementing the add operation because that’s all I’ll be using from my threads. Once all the values are together I’ll be returning the object to be read and manipulated from a single thread. (See previous post for the Countdown class and explanation of it.)

public static class ListThreadSafeExtensions
{
   public static void ThreadSafeAdd<T>(this List<T> list, T value)
   {
       object spinLock = ((ICollection)list).SyncRoot;

       lock(spinLock)
       {
           list.Add(value);
       }
   }
}

Now I call the code in a very similar manner as before:

var events = objectWithEvents.GetType().GetEvents();

//Previous way (void)
events.ParallelForEach(evt => evt.AddEventHandler(...);

//New addition (IEnumerable)
IEnumerable isMulticast = events.ParallelForEach(evt => evt.IsMulticast);

You can of course add as many extension methods as you like to implement the various Func overloads (all the way up to 8 parameters with a return value.) I only needed the one.

Your friendly neighborhood coder,
-Erik

[Update 11/1/2010 – Linked SyncRoot to MSDN doc about it.]

CAPAREA.NET Users Group

A coworker of mine will be presenting at the next Capital Area .Net Users Group on Tuesday, October 26, 2010 at 7:00PM in Vienna, VA. His presentation will be about new features in Entity Framework 4. Having used EF 1 (introduced in the .NET Framework 3.5 SP 1) for a small production web application I encountered a lot of quirks. Steve will be discussing how things have changed.

For those on the MD side he’s giving the same talk on November 2, 2010 at 6:30PM at the Central Maryland Associate of .Net Professionals at the HCC Business Training Center in Columbia, MD.

Also note that the CAPAREA.NET Special Interest Groups (Silverlight and SharePoint) will be moving location to Arlington, VA near the Court House metro stop. The current location will remain the home for the main user group meetings. Only the special interest groups are moving.

Toto too?
-Erik

CMAP Code Camp Fall 2010

A new coworker (the one I tech screened and prompted my call for Tech Screen ideas) reminded us about CMAP Code Camp Fall 2010. Details follow.

CMAP Code Camp Fall 2010 Is Here!

The Central Maryland Association of .NET Professionals (CMAP) is holding its Fall 2010 Code Camp on Saturday, November 6th, 2010 at the Loyola University Maryland Graduate Center in Columbia, MD.

The Code Camp will run from 8:30am – 5:30pm with 20-25 awesome sessions covering a wide range of database, software and portal development topics. It’s totally free. No gimmicks. No sales pitches. Enjoy breakfast and lunch at no charge while you mingle with your peers.

Code camps are a great way to pick up new knowledge and ideas as well as meet people who do what you do. I would stop short of calling it a networking function only because I don’t much care for those. But the learning! Oh, the learning!

Still not selling it? Um…Free Food?

1.21 Gigawatts,
-Erik

Fast Silverlight 4 Copy and Paste Context Menu [UPDATED]

My team recently deployed an early Beta release of a project for limited review. Of all the quirks and flaws, one stood out the most: users couldn’t right-click to copy and paste. A quick look for previous work on this topic turned up some stuff but what I found was based entirely on adding the functionality to one control at a time. This would take too long for us and since we use a variety of toolkit and 3rd party controls I decided to see if I could come up with something more generic.

For my first attempt I put the code directly in MainPage.xaml.cs which is the root control for our application. This first version worked with any control that exposed a SelectedText property but didn’t work on child windows. Still, the code was mostly useful so I pulled it out of MainPage and put it in its own control. For simplicity, I just extended the ContextMenu control available in the Silverlight 4 toolkit.

In Visual Studio I added a new Silverlight Control called PopupMenu.xaml. I then edited the XAML file to switch from UserControl to toolkit:ContextMenu and likewise in the class declaration of the associated CS file. I also ripped out the boilerplate XAML.

Then I created a method based on the original proof of concept code to handle MouseRightButtonDown and -Up methods. Using reflection I examined the controls in the visual tree under the mouse click to see if any of them offer a SelectedText property. If so, I check to see if it’s writable and if the control exposes a IsReadOnly property and if it’s false. If these conditions are met, the Copy, Cut and Paste menu options are presented to the user. (Alternatively just Copy if the SelectedText property is there but is not writeable or IsReadOnly is true.)

On loading of the MainPage control, I attach event listeners to the MouseRightButtonDown and -Up events passing some information onto an instance of the PopupMenu context menu control.

public partial class MainPage : UserControl
{
   private PopupMenu popupMenu = new PopupMenu();
   ...
   ...
   public MainPage()
   {
      InitializeComponent();

      this.MouseRightButtonDown +=
         new MouseButtonEventHandler(MainPage_MouseRightButtonDown);
      this.MouseRightButtonUp +=
         new MouseButtonEventHandler(MainPage_MouseRightButtonUp);
      ...
      ...
   }

   void MainPage_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
   {
      //Prevent generic Silverlight menu from popping.
      e.Handled = true;
   }

   void MainPage_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
   {
       popupMenu.HandleClick(e, this, false);
   }

This worked great for all our views based on Page but it still didn’t work for child windows. I decided that rather than go through all our child window controls and do the same as MainPage (wire up listeners and pass the calls on to PopupMenu) I would extend ChildWindow. I created a new control just like the PopupMenu. This time I changed UserControl to ChildWindow in the xaml and associated cs. In this class, ExtendedChildWindow, I attach the event listeners to the same mouse events and route the call just like MainPage.

public partial class ExtendedChildWindow : ChildWindow
{
   public ExtendedChildWindow()
   {
       InitializeComponent();

       if (!System.ComponentModel.DesignerProperties.IsInDesignTool)
       {
           this.MouseRightButtonDown +=
              new MouseButtonEventHandler(ExtendedChildWindow_MouseRightButtonDown);
           this.MouseRightButtonUp +=
              new MouseButtonEventHandler(ExtendedChildWindow_MouseRightButtonUp);
       }
   }

   void ExtendedChildWindow_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
   {
       new PopupMenu().HandleClick(e, this, true);
   }

   void ExtendedChildWindow_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
   {
       //Prevent generic Silverlight menu from popping.
       e.Handled = true;
   }

   ~ExtendedChildWindow()
   {
      this.MouseRightButtonDown -= ExtendedChildWindow_MouseRightButtonDown;
      this.MouseRightButtonUp -= ExtendedChildWindow_MouseRightButtonUp;
   }
}

Notice this time instead of newing up one PopupMenu control and using it over and over, I’m newing it each time. This is because for some reason I haven’t spent any time figuring out, if I don’t do it this way the offset goes crazy if I copy from a Page view before going into a child window and the menu is rendered in the lower-right corner of the Silverlight application. Doing it this way just works. Maybe in a future version I’ll try switching to a static method call so it doesn’t look as shady.

After that I went through all our controls based on ChildWindow (conveniently in their own solution folder) and changed them to inherit from my:ExtendedChildWindow. A few VS2010 crashes later I had all the source files updated. I ran the project and indeed the popup menu showed in views and child windows. Except in the child window controls the popup was shown in the upper left corner of the Silverlight application but it showed correctly for page views.

To fix this I added a boolean to the PopupMenu control. When true I would adjust the horizontal and vertical offset values based on the mouse position. With that in place I now had my final render tweaks working. I don’t know if this was the best way to go about it but this is how I took a proof of concept segment of code to working status integrated with the main source branch in less than 2 days.

Here are the important bits from the PopupMenu control code.

   ...
   ...
   [Flags]
   public enum TextOperations : ushort
   {
       Copy = 1,
       Paste = 2,
       Cut = Copy | Paste
   }

   public static TextOperations GetAllowedOperations(UIElement element)
   {
       TextOperations allowedOperations = new TextOperations();

       if (null != element.GetType().GetProperty("SelectedText"))
       {
           allowedOperations |= TextOperations.Copy;
       }
       if (null != element.GetType().GetProperty("SelectedText") &&
           element.GetType().GetProperty("SelectedText").CanWrite &&
           (null == element.GetType().GetProperty("IsReadOnly") ||
              (null != element.GetType().GetProperty("IsReadOnly") &&
               !bool.Parse(element.GetType().GetProperty("IsReadOnly")
                  .GetValue(element, null).ToString()))
               )
            )
       {
           allowedOperations |= TextOperations.Paste;                
       }

       return allowedOperations;
   }

   public void HandleClick(MouseButtonEventArgs e,
                                  UIElement displayElement,
                                  bool RenderContentOffset)
   {
       Point mousePosition = e.GetSafePosition(null);
       var elements = VisualTreeHelper
          .FindElementsInHostCoordinates(mousePosition, displayElement);

       TextOperations allowedOperations;
       foreach (var element in elements)
       {
           allowedOperations = GetAllowedOperations(element);

           if (allowedOperations > 0)
           {
               MenuItem option;
               Items.Clear();

               //Add menu items to this.Items
               ...

               //Now, if we found items, let's show and break out
               if (Items.Count > 0)
               {
                   ActiveElement = element;
                   if (RenderContentOffset)
                   {
                       HorizontalOffset = mousePosition.X;
                       VerticalOffset = mousePosition.Y;
                   }
                   IsOpen = true;
                   break;
               }
           }
       }
   }

   void SetSelectedText(UIElement element, string value)
   {
       element.GetType().GetProperty("SelectedText")
          .SetValue(element, value, null);
   }

   string GetSelectedText(UIElement element)
   {
       return element.GetType().GetProperty("SelectedText")
          .GetValue(element, null).ToString();
   }

   void ContextMenuItem_Click(object sender, RoutedEventArgs e)
   {
       if (null != ActiveElement)
       {
           MenuItem item = sender as MenuItem;

           switch (item.Header.ToString())
           {
               case "Cut":
               case "Copy":
                   Clipboard.SetText(GetSelectedText(ActiveElement));

                   if (item.Header.ToString() == "Cut")
                   {
                       SetSelectedText(ActiveElement, string.Empty);
                   }

                   break;
               case "Paste":
                   SetSelectedText(ActiveElement, Clipboard.GetText());
                   break;
           }
       }

       IsOpen = false;
       ActiveElement = null;
   }

Shiny?
-Erik

[UPDATE: 19 Oct 2010 @ 1:20PM]
One of the members on the team started getting cross-thread access errors that he was able to trace to the ExtendedChildWindow for removing the mouse event listeners. In an attempt to correct this, I’ve added a new event handler in the constructor to listen to the Unloaded event and moved the code to disconnect the event listeners into that handler. Hopefully this will resolve the issue.

NuPack for Visual Studio

I’ve been seeing a lot of tweets flying around regarding the CTP release of NuPack. If you’re not familiar with this project, I highly recommend taking a quick look at it. The basic premise of the project is this: make it easier for developers to integrate 3rd party components into their projects. Novel idea, huh?

I can hear a late-night pitch commercial for it already:

Tired of spending hours on the Internet researching components for your brilliant new project? Hate digging through pages and pages of comments to find the correct configuration setting? Wish there was a way to easily add features to your project so you can concentrate on other things? Well now there’s NuPack! It’s a .NET developer’s dream! It takes just minutes to install and it gives you access to a wealth of new features to choose from for your next big thing! Try it today!*
*Use of NuPack is not recommended for Perl developers, those who are or are expecting to become Rails evangelists, and program managers.

NuPack! Dependency resolution is only a click away!
-Erik

Dynamically Attaching Delegates Revisited

I previously wrote a post showing how, given a service with many events, I was able to dynamically attach an event handler based on certain conditions. This was done directly within my constructor for the object. Today I was looking at that same code and I couldn’t shake the feeling it looked odd having such a big segment of code in the constructor. I thought about moving it out to its own function and realized how many parameters I would have to send over. I decided to instead write an extension method.

At first I targeted the base class for my communication object but that would be tying the code to Silverlight. Right now that’s the only place I need it but I’ve done some code sharing between my Silverlight project and my WCF classes and I can easily see wanting to use this code over and over again. That said, here’s what I came up with:

public static class EventHandlerAttachmentExtensions
{
   public static void RegisterListenerForEvents(this object objectWithEvents,
                                 EventHandler genericHandler, Predicate eventCheck)
   {
      if (null == genericHandler)
         throw new ArgumentNullException("genericHandler");
      if (null == eventCheck)
         throw new ArgumentNullException("eventCheck");

      EventInfo[] events = objectWithEvents.GetType().GetEvents();
      foreach(EventInfo evt in events)
      {
         if (eventCheck(evt))
         {
            evt.AddHandler(objectWithEvents, Delegate.CreateDelegate(
                  evt.EventHandlerType, genericHandler.Target, genericHandler.Method));
         }
      }
   }
}

This extension method can be exposed on any object. This is because any object can define events. The upside is that we can use this on any object. The downside is this method extension will show up in every object in your project. You could change the base class to something more specific but I like the flexibility.

The delegate you pass in for the genericHandler must be public or you’ll get a MemberAccessException. If you don’t want your event handler public, then move the code into the class that defines the delegate and call it like a regular function rather than an extension.

The predicate for eventCheck is just a set of instructions the event must pass in order for the delegate to be attached. This gives you the ability to discriminate a little bit and ensure you only attach to events you care about.

If you want to use the ParallelForEach again, it works quite well. Just know that if for some reason the AddEventHandler call throws an exception you won’t know and this could lead to unexpected behavior. For generic code where I don’t have tight control over both sides of the equation, I prefer not to hide exceptions and let them bubble up. In .NET 4 with the AggregateException class maybe it would be alright to run in parallel and simply gather up the exceptions to be thrown at the end but I’m constrained to .NET 3.5 and this is the way I’ve chosen.

In my Silverlight project, where I once had all the code and logic embedded in my constructor, I now have:

public class ConnectionServer
{
   ...
   ...

   public void CheckForInvalidCondition(object sender, EventArgs e)
   {
      ... //Same as before
   }

   ConnectionService()
   {
      ...
      ...

      WcfClient.RegisterListenerFroEvents(
            CheckForInvalidCondition,
            evt => evt.EventHandlerType.IsGenericType &&
            null != evt.EventHandlerType.GetGenericArguments()[0].GetProperty("Result")
         );
   }
}

Take care,
-Erik

Tech Screen Questions

Recently I performed a tech screen on a candidate for my company. Through the process I realized how out of date the questions were for the type of work we do. One whole section was dedicated to WinForms and how/why you would override the drawing events. I decided I would weigh in on some helpful new topics and questions. It turns out there were previous efforts to modernize the evaluation form that stalled and since I’d shown initiative, I was handed the whole thing.

Side stepping the discussion of no good deeds going unpunished, I decided to seek feedback if anyone feels strongly enough to speak up.

We have two distinct skill sets for which we screen but it’s not required that you have all the specialized skills. My company is only interested in people who are late-intermediate to senior level and above and the topics should reflect this.

  • SharePoint, InfoPath, Worflow
  • MVC, Entity Framework, WPF, Silverlight, WCF

At the heart of it, all candidates need to pass standard .NET stuff including generics, garbage collection, proper OO design, etc. It should also include patterns, iterative development and, optimistically, test driven development.

I’ve got a small stash of topics and acceptable ranges of answers. If interested I could share the ones I’m thinking about working into the form but I’m curious what others think are good questions for evaluating a person’s comfort and competency with senior level programming.