Posts tagged Programming
Singleton tasks: A TaskFactory for the Task Parallel Library with ‘run-only-one’ semantics
Sep 1st
When developing .NET applications there is often the need to execute some slow background process repeatedly. For example, fetching a feed from a remote site, updating a user’s last logged in time, … etc. Typically you queue actions like these onto the thread pool. But under load that becomes problematic as requests may be coming in faster than you can service them, the queue builds up and you are now executing multiple requests for the same action when you only really needed to do one. Even when not under load, if two users request a web page that requires the same image to be loaded and resized for display you only want to fetch it and resize it once. What you really want is an intelligent work queue that can coalesce multiple requests for the same action into a single action that gets executed just once.
The new Task parallel library doesn’t have anything that can handle these ‘run-only-one’ actions directly but it does have all the necessary building blocks to build one by creating a new TaskFactory and using Task continuations.
Below is a TaskFactory that gives you ‘run-only-one’ actions. To use it you simply create a new TaskFactoryLimitOneByKey and then call StartNewOrUseExisting() with a suitable key, e.g. “FETCH/cache/image12345.jpg”. This method returns a normal Task object that you can Wait on or add more continuations. All the usual TaskFactory constructor options are provided so you can have a different TaskScheduler, common cancellation token, and other options.
Note also that it expects an Action<CancellationToken> not just a plain Action. This is so your Action can be polite and monitor the cancellation token to know when to stop early. If you don’t need that you can always pass in a closure that tosses the CancellationToken, i.e. (token) => MyAction().
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
namespace Utility
{
/// <summary>
/// A task factory where Tasks are queued up with a key and only one of that key is allowed to exist either in the queue or executing
/// </summary>
/// <remarks>
/// This is useful for tasks like fetching a file from backing store, or updating local information from a remote service
/// You want to be able to queue up a Task to go do the work but you don't want it to happen 5 times in quick succession
/// NB: This does not absolve you from using file locking and other techniques in your method to handle simultaneous requests,
/// it just greatly reduces the chances of it happening. Another example would be updating a user's last logged in data in a
/// database. Under heavy load the queue to write to the database may be getting long and you don't want to update it for the same
/// user repeatedly if you can avoid it with a single write.
/// </remarks>
public class TaskFactoryLimitOneByKey : TaskFactory
{
/// <summary>
/// Tasks currently queued based on key
/// </summary>
Dictionary<string, Task> inUse = new Dictionary<string, Task>();
public TaskFactoryLimitOneByKey()
: base()
{
}
public TaskFactoryLimitOneByKey(CancellationToken cancellationToken)
: base(cancellationToken)
{ }
public TaskFactoryLimitOneByKey(TaskScheduler scheduler)
: base(scheduler)
{ }
public TaskFactoryLimitOneByKey(TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions)
: base(creationOptions, continuationOptions)
{ }
public TaskFactoryLimitOneByKey(CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
: base(cancellationToken, creationOptions, continuationOptions, scheduler)
{ }
protected virtual void FinishedUsing(string key, Task taskThatJustCompleted)
{
lock (this.inUse)
{
// If the key is present AND it point to the task that just finished THEN we are done
// and can clear the key so that the next task coming in using it will get to execute ...
if (this.inUse.ContainsKey(key))
if (this.inUse[key] == taskThatJustCompleted)
{
this.inUse.Remove(key);
Debug.WriteLine("Finished using " + key + " completely");
}
else
{
Debug.WriteLine("Finished an item for " + key);
}
}
}
/// <summary>
/// Queue only one of a given action based on a key. A singleton pattern for Tasks with the same key.
/// </summary>
/// <remarks>
/// This allows you to queue up a request to, for example, render a file based on the file name
/// Even if multiple users all request the file at the same time, only one render will ever run
/// and they can all wait on that Task to complete.
/// </remarks>
public Task StartNewOrUseExisting(string key, Action<CancellationToken> action)
{
return StartNewOrUseExisting(key, action, base.CancellationToken);
}
/// <summary>
/// Queue only one of a given action based on a key. A singleton pattern for Tasks with the same key.
/// </summary>
/// <remarks>
/// This allows you to queue up a request to, for example, render a file based on the file name
/// Even if multiple users all request the file at the same time, only one render will ever run
/// and they can all wait on that Task to complete.
/// </remarks>
public Task StartNewOrUseExisting (string key, Action<CancellationToken> action, CancellationToken cancellationToken)
{
CancellationToken combined = cancellationToken == base.CancellationToken ? base.CancellationToken :
CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, base.CancellationToken).Token;
lock (inUse)
{
if (inUse.ContainsKey(key))
{
Debug.WriteLine("Reusing existing action for " + key);
return inUse[key]; // and toss the new action away
}
// otherwise, make a new one and add it ... with a continuation on the end to pull it off ...
Task result = new Task(() => action(combined), combined);
inUse.Add(key, result);
// queue up the check after it
result.ContinueWith((finished) => this.FinishedUsing(key, result));
Debug.WriteLine("Starting a new action for " + key);
// and finally start it
result.Start(this.Scheduler);
return result;
}
}
}
}
Email opt-out: Here’s a great example of how to do it right
Apr 27th
I came across this opt-out screen today. It’s one of the best examples I’ve seen recently of an opt-out screen done right.
First, they try to fix one of the key reasons people opt out of email: they are still interested but they want less email.
Then they give you the option to really just quit completely.
Then they give you the option to change your email address.
It really looks like they have done their homework, presenting these in the order that most likely applied whilst also trying to keep you as a recipient.
Anyone implementing email notifications for their startup should also take a look at CAN-SPAM.
DateTime values should always be stored in UTC
Feb 25th
Developers are sometimes confused about this issue but the fact of the matter is that you should always store Datetime values in your database in UTC and almost never in a local time zone.

photo credit: JBColorado
You should use UTC because:-
1) There are no ambiguous or missing times in UTC time. Any timezone with daylight savings time has a spring-forward gap and a fall-back repeated hour. That messes up all manner of calculations: How many hours is it from 2:05AM to 2:07AM? In UTC time it’s always 2 minutes but in local time it could be 2 minutes or it could be 1 hour and 2 minutes or it could be ‘error no such time’.
2) All your times sort correctly even if they were entered by users in different timezones. So, user A commenting on user’s B comment on user C’s photo doesn’t have their comments listed in the wrong order even if user C is in Europe, user A is in Japan and user B is in the USA. And user D gets to see the whole thread in whatever timezone they are in because you convert UTC to local on the way out in the user’s local timezone.
3) Daylight savings time rules change from time-to-time. To be able to reliably say how many hours it is from DateTime A to DateTime B you would need to store every historical variation in the DST rules in order to be able to calculate that correctly, and even then because of (1) you couldn’t calculate it in every case because there would be ambiguities.
4) Worse even that (3) is the fact that the boundaries of timezones are not constant but have changed over time. So your database of historical timezone information also needs to include accurate geographical information for every time zone AND you need to record the location of every local datetime value in order to be able to calculate when it happened in UTC time (and even then (1) causes problems).
5) If you think you understand timezones completely and can deal with all these issues go read up on Navajo Indian Reservations, fractional time zones and then consider what happens if you are recording datetime values associated with a moving vehicle.
Storing datetime values in UTC is the only sensible answer to all of these issues.
One of very few exceptions to this rule is when you have a local datetime that you cannot convert to UTC time because you can’t be sure of the timezone, e.g. Datetimes from digital cameras or camcorders where all you have is a local time and have no idea what timezone it is in. In such cases you can store a local datetime but you really have very little ability to do much with it apart from redisplay it.
The other one to watch for is where you have an event at a given time in a given location, e.g. 10AM: Family Reunion in Taos, New Mexico. In this case you need to do the UTC conversion in some timezone other than the one your user is in right now. And you want to store the fact that it is a time that should be shown in the local New Mexico timezone not the user’s timezone.
Grouping is another key issue – you need to convert your UTC times into local times BEFORE you group them into days because my ‘today’ might not be the same as your ‘today’. This complicates your ability to perform grouping in your database.
UTC is the only sensible format to store date time information in a database. If you can’t generate a UTC datetime from the input then the value you have may as well be stored as a string because there’s very little you can do with it without a lot of extra effort!
ASP.NET MVC 2 and the Ambiguous Match Exception for Action methods with different signatures
Feb 16th
One frustration I have with ASP.NET MVC is that you can’t easily have two actions with the same name but with different parameters, e.g. Index(int a, int b), and Index (int a). If you try this you will get an AmbiguousMatchException because it makes no attempt to match the form values with the method parameters to figure out which method you want to call. Now you can decorate the Index() with [AcceptVerbs(HttpVerbs.Get)] so that it at least will not be competing for ASP.NET MVC’s attention during the form post but your other two index methods will still cause the exception.
Supposed you wanted a page /Home/Index that had two forms on it:-
<%using (Html.BeginForm()) { %>
<%=Html.TextBox(“a”) %>
<input type=”submit” name=”submitOne” title=”click me” />
<%} %>
<%using (Html.BeginForm()) { %>
<%=Html.TextBox(“a”) %>
<%=Html.TextBox(“b”) %>
<input type=”submit” name=”submitTwo” title=”click me” />
<%} %>
What we’d like to do is be able to have three action methods, Index(), Index(Int a) and Index (Int a, Int b).
So let’s define our action methods like that and add a filter attribute to them that will filter methods according to the posted values ignoring any for which there aren’t enough posted values to match the number of parameters or for which the parameter names don’t match.
30 /// <summary>
31 /// Post a single integer back to the form, but don’t allow url /Home/Index/23
32 /// </summary>
33 [ParametersMatch]
34 [AcceptVerbs(HttpVerbs.Post)]
35 public ActionResult Index([FormValue]int a)
36 {
37 ViewData["Message"] = “You supplied one value “ + a ;
38
39 return View();
40 }
41
42 /// <summary>
43 /// Post two integers back to the form OR include two integers in the path
44 /// </summary>
45 [ParametersMatch]
46 [AcceptVerbs(HttpVerbs.Post | HttpVerbs.Get)]
47 public ActionResult Index([FormValue]int a, [FormValue]int b)
48 {
49 ViewData["Message"] = “You supplied two values “ + a + ” “ + b;
50
51 return View();
52 }
And finally, here’s the code that makes that possible: an attribute you can apply to a method parameter to indicate that you want it in the posted form, and an action filter that filters out any action methods that don’t match.
With this in place you can (i) avoid an unnecessary redirect and (ii) have actions with the same name but with different parameters.
Create a new ActionFilter like this …
1 namespace TestApplication.Controllers
2 {
3 using System;
4 using System.Collections.Generic;
5 using System.Collections.ObjectModel;
6 using System.Diagnostics.CodeAnalysis;
7 using System.Linq;
8 using System.Reflection;
9 using System.Web.Mvc.Resources;
10 using System.Web.Mvc;
11 using System.Diagnostics;
12
13
14 /// <summary>
15 /// This attribute can be placed on a parameter of an action method that should be present on the URL in route data
16 /// </summary>
17 [AttributeUsage(AttributeTargets.Parameter, AllowMultiple=false)]
18 public sealed class RouteValueAttribute : Attribute
19 {
20 public RouteValueAttribute() { }
21 }
22
23 /// <summary>
24 /// This attribute can be placed on a parameter of an action method that should be present in FormData
25 /// </summary>
26 [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
27 public sealed class FormValueAttribute : Attribute
28 {
29 public FormValueAttribute() { }
30 }
31
32
33 /// <summary>
34 /// Parameters Match Attribute allows you to specify that an action is only valid
35 /// if it has the right number of parameters marked [RouteValue] or [FormValue] that match with the form data or route data
36 /// </summary>
37 /// <remarks>
38 /// This attribute allows you to have two actions with the SAME name distinguished by the values they accept according to the
39 /// name of those values. Does NOT handle complex types and bindings yet but could be easily adapted to do so.
40 /// </remarks>
41 [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
42 public sealed class ParametersMatchAttribute : ActionMethodSelectorAttribute
43 {
44 public ParametersMatchAttribute() { }
45
46 public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
47 {
48 // The Route values
49 List<string> requestRouteValuesKeys = controllerContext.RouteData.Values.Where(v => !(v.Key == “controller” || v.Key == “action” || v.Key == “area”)).Select(rv => rv.Key).ToList();
50
51 // The Form values
52 var form = controllerContext.HttpContext.Request.Form;
53 List<string> requestFormValuesKeys = form.AllKeys.ToList();
54
55 // The parameters this method expects
56 var parameters = methodInfo.GetParameters();
57
58 // Parameters from the method that we haven’t matched up against yet
59 var parametersNotMatched = parameters.ToList();
60
61 // each parameter of the method can be marked as a [RouteValue] or [FormValue] or both or nothing
62 foreach (var param in parameters)
63 {
64 string name = param.Name;
65
66 bool isRouteParam = param.GetCustomAttributes(true).Any(a => a is RouteValueAttribute);
67 bool isFormParam = param.GetCustomAttributes(true).Any(a => a is FormValueAttribute);
68
69 if (isRouteParam && requestRouteValuesKeys.Contains(name))
70 {
71 // Route value matches parameter
72 requestRouteValuesKeys.Remove(name);
73 parametersNotMatched.Remove(param);
74 }
75 else if (isFormParam && requestFormValuesKeys.Contains(name))
76 {
77 // Form value matches method parameter
78 requestFormValuesKeys.Remove(name);
79 parametersNotMatched.Remove(param);
80 }
81 else
82 {
83 // methodInfo parameter does not match a route value or a form value
84 Debug.WriteLine(methodInfo + ” failed to match “ + param + ” against either a RouteValue or a FormValue”);
85 return false;
86 }
87 }
88
89 // Having removed all the parameters of the method that are matched by either a route value or a form value
90 // we are now left with all the parameters that do not match and all the route and form values that were not used
91
92 if (parametersNotMatched.Count > 0)
93 {
94 Debug.WriteLine(methodInfo + ” – FAIL: has parameters left over not matched by route or form values”);
95 return false;
96 }
97
98 if (requestRouteValuesKeys.Count > 0)
99 {
100 Debug.WriteLine(methodInfo + ” – FAIL: Request has route values left that aren’t consumed”);
101 return false;
102 }
103
104 if (requestFormValuesKeys.Count > 1)
105 {
106 Debug.WriteLine(methodInfo + ” – FAIL : unmatched form values “ + string.Join(“, “, requestFormValuesKeys.ToArray()));
107 return false;
108 }
109
110 Debug.WriteLine(methodInfo + ” – PASS – unmatched form values “ + string.Join(“, “, requestFormValuesKeys.ToArray()));
111 return true;
112 }
113 }
114 }
Issues combining ASP.NET MVC and ASP.NET Web Forms in the same application
Feb 6th
Recently I started migrating an ASP.NET WebForms project to ASP.NET MVC. Hoping to do this in phases I created a combined project that is both a webforms project and an MVC project.
Routing allows some requests to go to the WebForms pages and some to go to the new MVC pages.
Routing has also enabled SEO friendly URLs for all pages.
Everything seemed to be working great until I added a form to an MVC page and the URL it decided to use for posting the results back was one of the ASPX pages instead of the page it should have been. The issue was that routes added for the legacy ASPX pages were being picked up as matches for the route that was being requested.
This article was helpful in explaining how to configure routes to avoid this problem http://forums.asp.net/t/1484855.aspx but I still had an issue with the root “/” Route which was being picked for every form I created. So I changed the root route to this and now all is well. Of course, changing the home page to an MVC Action would also have solved the issue but I’m not ready to flip it just yet.
Route(“”,
new RouteValueDictionary(new { Controller = “Dummy”, Action = “Dummy” }),
new RouteValueDictionary(new { Controller = “Dummy”, Action = “Dummy” }),
routeHandler);
If it walks like a class, talks like a class, it probably is a class
Jan 31st
I occasionally come across attempts to extend Enums to include additional fields. These attempts typically use Attributes and reflection to get at the extra values. I have to say I don’t like them. The most extreme example of trying to get an Enum to do something else was this article on Code Project attempting to create a new type of enum: http://www.codeproject.com/KB/cs/EnumBuilder.aspx. Eugh!
Why do folks get so obsessed with trying to make enums do things that classes do better?
- As soon as you hit a limitation that an Enum can’t handle your best bet is to create a class.
- Need inheritance => use classes
- Need more than one value on the object => use a class
- Need more control over ToString() => use a class
- Need to be able to localize the string value => use a class
- …
- Might need to do any of these in the future => use a class
- If in doubt => use a class
If you do this your code will be
- more readable: you can say “x is Duck” instead of “x == Animal.Duck”
- more maintainable
- more extensible
- more object oriented (less switch statements and branching code)
- easier to localize (if you use the Enum’s name in the UI which isn’t a good practice anyway)
- almost certainly more efficient than using enums and reflection
The Blog of Ian Mercer: Home Automation++
Jan 26th
This is the blog of Ian Mercer, Serial entrepreneur, Digital Mapping Pioneer, Inventor of Windows Movie Maker, Microsoft Producer, HighMat, SnapTune, … Patent holder, Guinness world record holder and creator of a Natural Language Engine for .NET.
Here you’ll find my thoughts on Home automation, Natural Language Processing, Energy Conservation, Programming, Operations, Entrepreneurship, Business, Startups, Quality, Agile, Optimization, .NET, and more.
My home automation system recently won 1st and 3rd place in the international, Microsoft MyDotNetStory competition. You can view a demonstration of it under the home automation menu above. I believe that it is the world’s smartest house because I haven’t seen anything smarter. It controls lights, heating, sprinklers, audio, and more; it has hundreds of sensors including PIR, strain gauges, door switches, and more; it interfaces to Caller ID, PBX, Google Calendar, Google Contacts, Email, NOAA, Twitter, Facebook, RSS, Traffic, Podcasts and more. For the most part it works autonomously doing the right thing and reducing our energy consumption by over 40%. You can control it using a web, voice or chat interface. It has a unique Natural Language Interface that understands sentences and can hold a two-way conversation with you.
Thoughts under programming are mostly related to Microsoft’s .NET platform and the C# language but there are some that are more general in nature. I’ve been using Visual Studio 2010 and .NET 4 extensively recently including the Entity Framework, WCF, WPF and Silverlight.
You can view my professional profile on Linkedin or follow me on Twitter.



I’m also an avid photographer and videographer and I’m in the process of adding a few of my favorite pictures to the site.
Tip: getting the index in a foreeach statement
Dec 10th
Using LINQ you can easily get at the index in a foreach statement.
List x = new List() {"a", "b", "c"};
var augmented = x.Select((item, index) => new { item = s, index = index });
foreach (var d in augmented)
{
Console.WriteLine(d.item + " " + d.index);
}
Console.ReadKey();
a 0
b 1
c 2
SQL Server – error: 18456, severity: 14, state: 38 – Incorrect Login
Nov 16th
Despite the error message this problem can be caused by something other than an Authorization failure. In fact, simply misspelling the Initial Catalog can cause this message to appear. I wish developers wouldn’t reuse error messages when the problem and solution is completely different.
Cloud computing – where’s the silver lining?
Mar 8th
Posted by Ian Mercer in Commentary
Cloud Computing - where's the silver lining?
I’ve seen several people propounding the cost savings of cloud computing as being of great benefit to startups. Most recently someone wrote “… cloud offers an amazing opportunity to reduce costs for startups”
This simply isn’t true.
It cost ~$2500 to buy a smoking hot server from Silicon Mechanics with SSD drives and under $100/month to host it at a reputable data center. Over 4 years that’s about $160/month which is less than coffee and a doughnut each day. Even if the cloud was free that still wouldn’t make it an “amazing” cost saving.
In addition, said smoking hot server, can outperform 8 large EC2 instances on any compute heavy or data intensive operation. For individual web requests with some database access it also offers lower latencies = better customer experience.
Depending on the load, cloud computing can cost more than a dedicated server and offer a worse customer experience. It’s not the panacea it’s made out to be.
The ‘correct’ reasons to select cloud computing are …
“Cost savings” doesn’t even make the list for startups IMHO and many of these same benefits can be had by running your own smoking hot server with virtualization.
The other dirty secret of cloud computing concerns the notion that you can pull together a reliable system from disparate services from different vendors. Do the math: 0.999 x 0.999 x 0.999 x 0.999 is a lot less than 0.999 and that could mean unacceptable downtime for your users.
Summary: It’s not significantly cheaper, it may be slower, it may be less reliable but it can be much more convenient.