Hope this makes Eric smile a little. A question on TinyClr NETMF forum prompted this. The question was related to looking at a Cpu.Pin stream for a certain pattern. Right away I thought of Rx. However a 35K+ port of Rx is overkill. But mixing in some of the ideas, I was able to come up with two (very handy I think) extention methods that get the job done in a composable way.  You subscribe to an event pin with an observer and do what you need.  I thought it was cool.

public delegate bool PinChange(bool state, DateTime time);
public delegate bool PinChangeSpan(bool state, long tickSpan);
public static class Extentions
{
    /// <summary>
    /// This overload passes tick span between pin changes.
    /// </summary>
    public static void Subscribe(this InterruptPort port, PinChangeSpan predicate)
    {
        if (predicate == null) throw new ArgumentNullException("predicate");
        long lastTick = -1;
        port.Subscribe((bool state, DateTime dt) =>
            {
                if (lastTick < 0)
                {
                    lastTick = dt.Ticks;
                    // The first "real" pin change has no delta yet.
                    return predicate(state, -1);
                }
                long delta = dt.Ticks - lastTick;
                lastTick = dt.Ticks;
                return predicate(state, delta);
            }, 1); // Always skip first as dirty because no idea when it was set.
    }

    /// <summary>
    /// This overload passes DateTime of current pin state.
    /// </summary>
    /// <param name="predicate">User predicate.</param>
    /// <param name="skipCount">Number of changes to skip.</param>
    public static void Subscribe(this InterruptPort port, PinChange predicate, uint skipCount=0)
    {
        if (predicate == null) throw new ArgumentNullException("predicate");
        NativeEventHandler del = null;
        del = (uint data1, uint data2, DateTime time) =>
        {
            if (skipCount > 0)
            {
                skipCount--;
                return;
            }

            if (del == null)
                return; // Already unregisted. Not sure why this needed to avoid extra callback. MF Bug?

            bool state = data2 == 0 ? false : true;
            // If user predicate not want more, then unregister.
            if (! predicate(state, time))
            {
                port.OnInterrupt -= del;
                del = null;
            }
        };

        // Register observer.
        port.OnInterrupt += del;
    }
}

Usage samples:

 
InterruptPort inPort = new InterruptPort((Cpu.Pin)FEZ_Pin.Interrupt.Di13, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);

int highCount = 0; // local state var.
inPort.Subscribe((isHigh, dt) =>
{
    if (isHigh && ++highCount >= 5)
    {
        Debug.Print("Pin high 5 times. Do something.");
        return false; // unsubscribe.
    }
    return true; // keep subscription active.
});

// PulseIn sample:
// Milliseconds span between first low and high.
inPort.Subscribe((bool isHigh, long ticks) =>
{
    if (ticks == -1)
        return true; // Skip first, because we have no delta time context yet. 
    if (isHigh)
    {
        Debug.Print("\nDelay between first low and first high: " + ticks / 10000);
        return false; // done.
    }
    else
        return true;
});