Turns out that C# doesn't actually let you do this. It compiles and
runs, but just silently fails to hook the event. Something to do with
the EventHandler delegate magic... maybe a "+= on a struct" kind of
thing?
An `EventAwaiter` timeout now throws a `TimeoutException` instead of a
`TaskCanceledException`.
Disconnecting a micro:bit while subscribed for change notifications was
causing an exception because a notification was being triggered after
the socket closed. Fixing that led to an attempt to close the socket
after it was closed and set to `null`. That one was solved with a null
check.
For BT, connection is still not reliable but it's a step in the right
direction... I think. The socket lock is now held while opening the
RFCOMM channel, which is an awful long time to hold a lock, but really
no other thread should be messing with the socket during that time so I
guess it's the right thing to do. I also added debug printouts on the
RFCOMM event delegate.