Cancel That

Cancellation in a multi-threaded Console App can be surprisingly difficult, even though I’ve done it dozens (hundreds?!?) of times before.  As any programmer can tell you, there are the “Things you know” and “Things you merely think you know.”  In programming, fiddly little details count.

I won’t go into the trade-offs between using Tasks or Parallel.For[Each] or TPL DataFlow, but suffice it to say that the later is both the most useful and easiest to get right.  Enjoy…

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;

namespace CancelDemo
{
   class Program
   {
      static void Main(string[] args)
      {
         Console.WriteLine("Press any key to cancel...");
         Console.WriteLine();

         var cts = new CancellationTokenSource();

         var client = new HttpClient();

         try
         {
            var fetcher = new ActionBlock<string>(
               async url =>
               {
                  await client.GetAsync(url, cts.Token);

                  Console.WriteLine($"FETCHED {url}");
               },
               new ExecutionDataflowBlockOptions()
               {
                  CancellationToken = cts.Token,
                  MaxDegreeOfParallelism = Environment.ProcessorCount
               });

            urls.ForEach(url => fetcher.Post(url));

            fetcher.Complete();

            var readKey = new TaskFactory(cts.Token).StartNew(() =>
            {
               while (!Console.KeyAvailable)
                  Thread.Sleep(100);

               cts.Cancel();

               Console.ReadKey(true);
            });

            Task.WaitAny(new Task[] { fetcher.Completion, readKey });
         }
         catch (OperationCanceledException)
         {
         }
         catch (Exception error)
         {
            cts.Cancel();

            Console.WriteLine("Error: " + error.Message);
         }

         Console.WriteLine();
         Console.Write("Press any key to terminate...");

         Console.ReadKey(true);
      }

      private static List<string> urls = new List<string>()
      {
         "https://www.pinterest.com/pin/143270831869696811/",
         "https://www.pinterest.com/pin/155585362100632165/",
         "https://www.pinterest.com/pin/23010648069511614/",
         "https://www.pinterest.com/pin/303711568591359002/",
         "https://www.pinterest.com/pin/314900198915723688/",
         "https://www.pinterest.com/pin/316166836311260373/",
         "https://www.pinterest.com/pin/535576580657166380/",
         "https://www.pinterest.com/pin/56154326576327972/",
         "https://www.pinterest.com/pin/56154326576368600/",
         "https://www.pinterest.com/pin/88523948898601589/",
         "https://www.pinterest.com/pin/108438303498183811/",
         "https://www.pinterest.com/pin/127156389453876236/",
         "https://www.pinterest.com/pin/270708627574674608/",
         "https://www.pinterest.com/pin/368380444492800731/",
         "https://www.pinterest.com/pin/250653535491278041/",
         "https://www.pinterest.com/pin/565483296932119884/",
         "https://www.pinterest.com/pin/173177548141309276/",
         "https://www.pinterest.com/pin/430867889333901210/",
         "https://www.pinterest.com/pin/61361613645883874/",
         "https://www.pinterest.com/pin/16466354858074206/"
      };
   }
}


I used to live here, but now I’m just Code Camping out!

Just for fun, because who doesn’t like to wake up ridiculously early on a Saturday morning to take a train from Philliy into good ‘ole NYC, I decided to do some major tongue-wagging at Code Camp NYC 2013.  I mean, what could be better.  I won’t get paid, and let’s not even mention the food, so there’s that.  On the other hand, a chance to bloviate in front of a fresh and unsuspecting crowd seems just too good to stay away.  To that end, I prepared an obligatory PowerPoint, then wrote some moderately interesting code: LogFlow and PodFetch.  I even pulled together a ton of samples, a small number of which are actually mine!  Should be a blast.  Hope to see you there….

BTW, I always wanted to make it to Carnegie Hall.  I think I’ll have to settle for the “Carnegie” room; from 2:30pm to 3:45pm.  My session is titled “Supercharge Your Apps With TPL Dataflow.”

Guuuuuuuuuuuuuuuulp!

Truth be told, like most of my ilk—programmers—I’m a closet megalomaniac.  I want to wield power, to envision and forge new worlds, to grapple with the nearly ungrappleable.  More to the point, I’m more than a little convinced that I’m just the man for the job.

On most days, this sort of thing tends to be fairly out of reach.  On this day, though, I got to build Gulp! Continue reading