25 May 2012

Windows 8 Boot Camp: Johannesburg 24 May

imageYesterday Rudi Grobler & I had awesome fun with a full room of amazing people who took time off work to attend a full day of free Windows 8 training. The audience was amazing, breaking a lot of my expectations of how audiences react at free events, which really honoured Rudi & I to have most people stay to the very end of the day.

5b

For those people who attended the training, or those who didn’t but want the content too:

AttachmentSize
Windows 8 Demos551.64 KB
09 May 2012

.NET 4.5 Baby Steps, Part 8: AppDomain wide culture settings

Other posts in this series can be found on the Series Index Page

Introduction

Culture settings in .NET are a very important but often ignored part of development, they define how numbers, dates and currencies are displayed and parsed and you application can easily break when it is exposed to a new culture.

In .NET 4, we could do three things:

  • Ignore it
  • Set it manually everywhere
  • If we were using threads, we could set the thread culture.

So lets see how that works:

// uses the system settings
Console.WriteLine(string.Format("1) {0:C}", 182.23));

// uses the provided culture
Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "2) {0:C}", 182.23));

// spin up a thread - uses system settings
new Thread(() =>
    {
        Console.WriteLine(string.Format("3) {0:C}", 182.23));
    }).Start();

// spin up a thread - uses thread settings
var t = new Thread(() =>
{
    Console.WriteLine(string.Format("4) {0:C}", 182.23));
});

t.CurrentCulture = new CultureInfo("en-us");

t.Start();

Console.ReadLine();

CropperCapture[2]

You can see in the capture above lines 1 & 3 use the South African culture settings it gets from the operating system. What if I want to force say an American culture globally? There was no way before .NET 4.5 to do that.

What .NET 4.5 adds?

By merely adding one line to the top of the project, all threads, including the one we are in get the same culture:

CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-us");

CropperCapture[1]

AttachmentSize
Culture Info Demo33.41 KB
09 May 2012

.NET 4.5 Baby Steps, Part 7: Regular Expression Timeouts

Other posts in this series can be found on the Series Index Page

Introduction

While the regular expression passing in .NET is damn fast, there are times where it can take too long for your needs. Until now there hasn’t been much you can do but wait. In .NET 4.5 we get the ability to timeout regular expressions if they took too long.

Problem

So lets look at a really silly example to start off with, checking a string fifty million characters (where only one is different) against regular expression which is looking for fifty million letters. As I said it is silly, but to get a truly slow reg ex is pretty hard.

static Regex match = new Regex(@"\w{50000000}", RegexOptions.None);
static void Main(string[] args)
{
    var sw = Stopwatch.StartNew();
    Console.WriteLine(match.IsMatch(String.Empty.PadRight(49999999, 'a') + "!"));
    sw.Stop();
    Console.WriteLine(sw.Elapsed);
    Console.ReadLine();
}

This 13.5secs on my machine!

Solution

imageAll we need to do to take advantage of the new timeouts is modify the constructor of the Regex, by adding a third parameter.

static Regex match = new Regex(@"\w{50 000 000}", RegexOptions.None, TimeSpan.FromSeconds(5));

Now after five seconds a RegexMatchTimeoutException is raised.

AttachmentSize
RegEx timeout demo32.73 KB
09 May 2012

.NET 4.5 Baby Steps, Part 5: Some more interesting blocks

Other posts in this series can be found on the Series Index Page

Introduction

We have seen the IDataFlowBlock, in three different implementations and now we will look at a few more.

BroadcastBlock<T>

In the BatchBlock we saw that if you had multiple subscribers, messages are delivered to subscribers in a round robin way, but what about if you want to send the same message to all providers? The solution is the BoardcastBlock<T>.

static BroadcastBlock<string> pubSub = new BroadcastBlock<string>(s =>
    {
        return s + " relayed from publisher";
    });

static async void Process()
{
    var message = await pubSub.ReceiveAsync();
    Console.WriteLine(message);
}

static void Main(string[] args)
{
    // setup 5 subscribers
    for (int i = 0; i < 5; i++)
    {
        Process();
    }

    pubSub.Post(DateTime.Now.ToLongTimeString());

    Console.ReadLine();
}
CropperCapture[1]

TransformBlock<TInput,TOutput>

The next interesting block is the transform block which works similar to the action block, except that the input and output can be different types and so we can transform the data internally.

static TransformBlock<int, string> pubSub = new TransformBlock<int, string>(i =>
    {
        return string.Format("we got: {0}", i);
    });

static async void Process()
{
    while (true)
    {
        var message = await pubSub.ReceiveAsync();
        Console.WriteLine(message);
    }
}

static void Main(string[] args)
{
    Process();
     
    for (int i = 0; i < 10; i++)
    {            
        pubSub.Post(i);
        Thread.Sleep(1000);
    }

    Console.ReadLine();
}
CropperCapture[1]
AttachmentSize
Broadcast Block Demo36.31 KB
Transform Block Demo7.9 KB
09 May 2012

.NET 4.5 Baby Steps, Part 6: ISourceBlock

Other posts in this series can be found on the Series Index Page

Introduction

We have spent a number of posts looking at IDataFlowBlock, BatchedBlocks and some other interesting blocks but as a final interesting bit for blocks is the ISourceBlock interface which is implemented on the “publisher” like blocks and it has a very interesting method: LinkTo. The goal of LinkTo is to chain blocks together to do interesting and amazing things!

It's in the name

The final interesting point, and likely the most important is in the name of the assembly all this goodness comes from: System.Threading.Tasks.DataFlow. All of this is handled my multiple tasks (and likely multiple threads) under the covers without you needing to worry about it. When we look at the TPL in .NET 4 and how it made working with multi-threaded processing easier, the final goal of this is to make multi-threaded data processing easier - and it does!

Demo LinkTo

In this demo what we want to do is take in DateTime’s as fast as possible, then convert them to strings, and send them in batches to the three subscribers. Sounds complex, but with the ability to LinkTo this is very easy.

static BufferBlock<DateTime> bufferPublisher = new BufferBlock<DateTime>();
static TransformBlock<DateTime, string> transformPublisher = new TransformBlock<DateTime, string>(d =>
    {
        return d.ToLongTimeString();
    });
static BatchBlock<string> batchPublisher = new BatchBlock<string>(5);

static ActionBlock<string[]> subscriber1 = new ActionBlock<string[]>(s =>
    {
        Console.WriteLine("Subscriber 1: {0}", s);
    });
static ActionBlock<string[]> subscriber2 = new ActionBlock<string[]>(s =>
{
    Console.WriteLine("Subscriber 2: {0}", s);
});

static ActionBlock<string[]> subscriber3 = new ActionBlock<string[]>(s =>
{
    Console.WriteLine("Subscriber 3: {0}", s);
});


static void Main(string[] args)
{
    batchPublisher.AsObservable().Subscribe(subscriber1.AsObserver());
    batchPublisher.AsObservable().Subscribe(subscriber2.AsObserver());
    batchPublisher.AsObservable().Subscribe(subscriber3.AsObserver());

    transformPublisher.LinkTo(batchPublisher);
    bufferPublisher.LinkTo(transformPublisher);

    for (int i = 0; i < 100; i++)
    {
        bufferPublisher.Post(DateTime.Now);
        Thread.Sleep(200);
    }

    Console.ReadLine();
}
CropperCapture[1]
AttachmentSize
LinkTo Demo7.75 KB
09 May 2012

.NET 4.5 Baby Steps, Part 4: BatchedBlocks

Other posts in this series can be found on the Series Index Page

Introduction

We previously looked at the IDataFlowBlock interface in it’s simplest implementation ActionBlock<TInput>, today though we are going to look at more complex implementations that give amazing powers.

BatchBlock<T>

CropperCapture[1]Where ActionBlock<TInput> could only be a subscriber, BatchBlock<T> is more than that – it can be a subscriber and a publisher rolled into one! As such the usage is rather different, we do not pass in the receive method in the constructor. Rather we call the Receive method to get the latest messages past to the subscriber.

The interesting thing about BatchBlock is it batches up messages into groups, so rather than getting each message one at a time, you get groups of messages. As such, you could wait a long time for enough the messages to arrive, so thankfully they also include a ReceiveAsync which works with C# new async methods.

In the sample below you can see how I create a BatchBlock with a batch size of 3, so messages get processed in groups of three. This also means the last two messages (since we are sending 20) are never processed.

static BatchBlock<string> pubSub = new BatchBlock<string>(3);
static int counter = 0;

static async void Process()
{
    while (true)
    {
        var messages = await pubSub.ReceiveAsync();
        foreach (var item in messages)
        {
            counter++;
            Console.WriteLine("Got message number {0}: {1}", counter, item);
        }
    }
}

static void Main(string[] args)
{
    Process();

    for (int i = 0; i < 20; i++)
    {
        Task.Factory.StartNew(() =>
        {
            Thread.Sleep(new Random().Next(200, 1000));
            pubSub.Post(DateTime.Now.ToLongTimeString());
        });
    }

    Console.ReadLine();
}

 

BatchedJoinBlock<T1,T2>

CropperCapture[1]The second block implementation we look at is the BatchedJoinBlock<T1,T2> which is similar to BatchBlock<T> except, that it has multiple type inputs. This allows you to have a single publisher that can send messages to different subscribers based on type! The batching works the same as before, but be careful as batch sizes are based on all messages regardless of types.

static BatchedJoinBlock<string, int> pubSub = new BatchedJoinBlock<string, int>(3);
static int stringCounter = 0;
static int intCounter = 0;

static async void Process()
{
    while (true)
    {
        var messages = await pubSub.ReceiveAsync();
        foreach (var item in messages.Item1)
        {
            stringCounter++;
            Console.WriteLine("Got STRING message number {0}: {1}", stringCounter, item);
        }

        foreach (var item in messages.Item2)
        {
            intCounter++;
            Console.WriteLine("Got INT message number {0}: {1}", intCounter, item);
        }
    }
}

static void Main(string[] args)
{
    Process();

    for (int i = 0; i < 20; i++)
    {
        Task.Factory.StartNew(() =>
        {
            Thread.Sleep(new Random().Next(200, 1000));
            pubSub.Target1.SendAsync(DateTime.Now.ToLongTimeString());
        });

        Task.Factory.StartNew(() =>
        {
            Thread.Sleep(new Random().Next(200, 1000));
            pubSub.Target2.SendAsync(new Random().Next(1, 99));
        });
    }

    Console.ReadLine();
}

Multiple Subscribers

CropperCapture[2]So what happens when you add multiple subscribers to the system? It handles each processing in a round robin like way. The sample below is the same as the BatchBlock<T> about, but  has three subscribers (A, B & C) and a batch size of two.

static BatchBlock<string> pubSub = new BatchBlock<string>(2);
static int counter = 0;

static async void Process(string id)
{
    while (true)
    {
        var messages = await pubSub.ReceiveAsync();
        foreach (var item in messages)
        {
            counter++;
            Console.WriteLine("{2} - Got message number {0}: {1}", counter, item, id);
        }
    }
}

static void Main(string[] args)
{
    Process("A");
    Process("B");
    Process("C");

    for (int i = 0; i < 11; i++)
    {
        Task.Factory.StartNew(() =>
        {
            Thread.Sleep(new Random().Next(200, 1000));
            pubSub.Post(DateTime.Now.ToLongTimeString());
        });
    }

    Console.ReadLine();
}
08 May 2012

.NET 4.5 Baby Steps: Series Index

This page lists is just a list of the various posts in the .NET 4.5 Baby Steps series. If the page is grey or not a link then it is because the post is not published yet and you should check back soon.

08 May 2012

.NET 4.5 Baby Steps, Part 3: IDataFlowBlock

Other posts in this series can be found on the Series Index Page

Introduction

A new interface in .NET is the IDataFlowBlock, which is implemented in many interesting ways, so to look at those we will start off with the simplest implementation. ActionBlock<TInput> is a completely new class in .NET 4.5 and provides a way of working with data in a very task orientated way. I simplistically think of this as the implementation of the IObserver interface we got in .NET 4. but do not limit your thinking to just that.

To use it, you first must add a reference to System.Threading.Tasks.DataFlow

image

In this simple first example I am doing a fairly simple Pub/Sub demo:

var subscriber = new ActionBlock<string>(input =>
    {
        Console.WriteLine("Got: {0}", input);
    });

for (int i = 0; i < 10; i++)
{
    Task.Factory.StartNew(() =>
        {
            Thread.Sleep(new Random().Next(200, 1000));
            subscriber.Post(DateTime.Now.ToLongTimeString());
        });
}

Console.ReadLine();
CropperCapture[3]

As IObserver<T>

So the first fantastic feature is that it does have the ability (via extension method) to be an IObsserver<T> so it really solves the need to build up your own subscriber classes when implementing a pub/sub model.

First is the code for the publisher class – this is normal for the IObservable<T> as we had in .NET 4. This just means our new code can play well with our existing code.

public class Publisher : IObservable<string>
{
    List<IObserver<string>> subscribers = new List<IObserver<string>>();

    public IDisposable Subscribe(IObserver<string> observer)
    {
        subscribers.Add(observer);
        return null;
    }

    public void Send()
    {
        foreach (var item in subscribers)
        {
            item.OnNext(DateTime.Now.ToLongTimeString());
        }
    }
}

For our demo code, which produces the same as above:

var publisher = new Publisher();

var subscriber = new ActionBlock<string>(input =>
    {
        Console.WriteLine("Got: {0}", input);
    });

publisher.Subscribe(subscriber.AsObserver());

for (int i = 0; i < 10; i++)
{
    Task.Factory.StartNew(() =>
        {
            Thread.Sleep(new Random().Next(200, 1000));
            publisher.Send();
        });
}

Complete

The next awesome feature is the Complete method which can be used to stop accepting of input when called – this is great for services where you want to shut down.

In this demo code it will run until you press enter:

var subscriber = new ActionBlock<string>(input =>
{
    Console.WriteLine("Got: {0}", input);
});


Task.Factory.StartNew(() =>
{
    while (true)
    {

        Thread.Sleep(new Random().Next(200, 1000));
        subscriber.Post(DateTime.Now.ToLongTimeString());
    }
});

Console.WriteLine("Press any key to stop input");
Console.ReadLine();
subscriber.Complete();
AttachmentSize
ActionBlock<T> demos8.36 KB
Tags: 

Pages

dontclickme