Thursday, September 30, 2010

Rethrowing Exceptions Without Losing Original Stack Trace

Everyone knows you should never ‘throw err’:

    try

    {

        // Do something bad

    }

    catch(Exception err)

    {

        // Some error handling, then…

        throw err;

    }

 

…because you overwrite the original stack trace, and end up with no idea what happened where. If you want to re-throw, you just ‘throw’ within the catch block, and the original exception is re-throw unmodified (or wrap-and-throw).

But that’s within the catch block. What do you do if you need to re-throw an exception outside the catch, one you stored earlier? This is exactly what you have to do if you’re implementing an asynchronous (APM / IAsyncResult) call, or marshalling exceptions across app domain / remoting boundaries.

The runtime manages this just fine by ‘freezing’ the exception stack trace. When rethrow, the new stack trace is just appended to the old one – that’s what all those ‘Exception rethrow at [0]’ stuff is in the stack trace. But the method it uses to do this (Exception.PrepForRemoting) is internal. So unfortunately in order to use it, you have to call it by reflection:

    public static void PrepForRemoting(this Exception err)

    {

        typeof(Exception).InvokeMember(

            "PrepForRemoting",

            BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod,

            (Binder)null, err, new object[0]);

    }

 

    /// <summary>

    /// Rethrow an exception without losing the original stack trace

    /// </summary>

    [DebuggerStepThrough]

    public static void Rethrow(this Exception err)

    {

        err.PrepForRemoting();

        throw err;

    }

Evil I here you cry? Well suck it up, because that’s exactly what Rx does in System.CoreEx:

image

(Tasks in .Net 4 side-step this problem by always wrapping exceptions in a new AggregateException prior to throwing – this also allows a Task to accumulate multiple exceptions throughout its lifecycle, depending on the continuations applied)

Sunday, September 19, 2010

Reacting to Rx

I’ve finally got round to spending a bit of time looking at Rx over the weekend, and my head is still spinning as to just how fantastically relevant this is to some of the stuff I’m working on right now. If have no idea what Rx is, check out these brief Channel 9 videos:

The first will get you interested, the second will make the penny drop[1].

So anyway, I have a class called a MessagePump<T>. Its job is to abstract away a lot of low-level socket guff (fragmentation, parsing etc…) and just deliver messages as they are read off a socket. It basically just sits in a big async loop of BeginRead / EndRead operations, constantly passing itself as the callback (ie never ‘owning’ a thread).

That’s all it does, so to deliver messages into the rest of the system it exposes a MessageReceived event. And sometimes a message might not parse properly, probably someone got out of sync whatever, so there’s a ExceptionReceived event. Oh, and if you get a zero-byte read from BeginRead that means the socket the other end closed, so there’s a Disconnected event

  • MessageReceived(object, EventArgs<T>)
  • ExceptionReceived(object, EventArgs<Exception>)
  • Disconnected(object, EventArgs)

Now compare this to Rx’s IObserver<T> interface:

  • OnNext(T)
  • OnError(Exception)
  • OnCompleted()

It’s like completely the same. I guess there are only so many ways to skin a cat, but I wasn’t expecting it to be quite so aligned. Hopefully I can read this as saying my design is basically sound.

But whatever, what it really means is that dropping in Rx is going to be a bit of a doddle. In fact because the IObserver<T> and IObservable<T> interfaces (alone) are part of the .net 4 framework, even without Rx I can implement the pattern (just without the Rx fruit),which makes leveraging Rx later on (e.g. to filter with Linq) an option for the consumer.

And because the IObserver<T> / IObservable<T> pattern is much more amenable to composition than a raw .net event (which is really, the whole point of Rx), we can use containers like MEF to attach the subscribers at runtime, with (what seems to be) relative ease.

Both temporal and binary decoupling. Cool.

 

[1] For example: did you ever write something like an auto-complete popup? You want to wait a while after each keystroke in case the user didn’t finish typing yet (about 500ms I think). I ended up writing a general-purpose event-buffer class, that only propagated the event after a specified inactivity period (this also worked great for file change notifications). In Rx this is trivial: just use the ‘Throttle’ linq operator over the event sequence. See the hands-on-lab

Saturday, September 18, 2010

Problems With Stuff

image

Being charitable you might point out that as a technology becomes increasingly pervasive it inevitably ends up in the hands of less technically savvy users, but I like to think of it as ‘all our stuff is still a bit crap’.

Wednesday, September 08, 2010

.Net 4 not supported on Windows 2008 Server Core

There is an explanation from the .net SKU owner as to why (which I don’t entirely follow), but the bottom line is that what the download page says is right – it’s just not available. So no Distributed Cache either.

Poo.

(It does support a subset of the net 3.5 functionality, largely orientated towards ASP.Net support – there’s a basic explanation of which bits here)

Visual Studio 2010 build spew in DebugView

If you’re a fan of DebugView (like me) you’d have been driven spare by the reams of spurious debug output that VS 2010 generates when doing a build: some 15,000 lines (in my case) of repeated cruft that drowns your output:

*** HR originated: -2147024774
*** Source File: d:\iso_whid\x86fre\base\isolation\com\copyout.cpp, line 1302


*** HR propagated: -2147024774
*** Source File: d:\iso_whid\x86fre\base\isolation\com\enumidentityattribute.cpp, line 144



This is a known issue on the forums, and there is a Connect Issue associated with it, so please vote for it. Hopefully it’s not too late to get this fixed in SP1.



(I’m optimistic– the bug was raised by Rusty Miller, an (erstwhile?) tester on the VS team)

Tuesday, September 07, 2010

TechEdAu 2010

It was only the week before last, but already I feel the clarity slipping away like a dream in the morning. Ahem. It was quite an interesting year, because apart from Windows Mobile 7, most of the stuff that was being talked about actually exists at RTM today, which was a nice change from learning about stuff you might get to use in 6 month’s time.

Memes this year:

  • Devices are ‘windows’ to the cloud [1]
  • Virtualisation, virtualization, virtualization
  • All I want for Christmas is Windows Mobile 7

Anyway, here’s what I went to

Day 1:

Day 2:

Day 3:

And here’s all the sessions I will be catching up on Online (as and when the videos come up):

…and a couple from TechEd North America that looked fairly promising:

Phew.

 

[1] If you think this cloud stuff is finally becoming the William Gibson / Ian M Banks model of pervasive cyberspace, you’d be right.

Saturday, September 04, 2010

Which WPF Framework?

So it’s way past time that I actually started getting used to a WPF framework, rather than keep re-inventing the wheel. But where to start? I thought it was just between Prism and Caliburn, but then I found WAF, and then researching that I found a whole bunch of others.

I suspect I’ll start with WAF because it describes itself as lightweight. Prism comes from the P&P team, who are normally anything but, and Caliburn supports paradigms other than MVVM, which just seems a bit pointless.

Popular Posts