Last night we finished a two week driving holiday to the eastern states (Victoria, New South Wales and Queensland). It’s trips like this that make you realise how vast the continent of Australia is (and how nice it would be to be able to fly everywhere instead of driving!).
It also reinforces my respect for those who choose to live and work in these remote regions.
Highlights of the trip were the Pioneer Settlement in Swan Hill,
a paddle-steamer ride in Echuca,
a few days in a Bed and Breakfast in Grafton, NSW,
Some fun at Dreamworld in Queensland (yes, the kids are in there with me),
more driving down through the Gold Coast (No, we’re not racing),
Before heading back home again. Our final day was from Parkes, NSW back to Adelaide – at 1,000 kms the longest distance we did in a single day.
It is good to be home again. Needless to say, I’m glad I’ve got a couple more days to recover before I go back to work.
It isn’t the end of my travels though. I’m off again in a couple of weeks to visit RL Solution’s Toronto office for a week, before going to my first MVP Summit at Microsoft’s campus in Seattle.
In the early hours of this morning I received an email from Microsoft:
Dear David Gardiner,
Congratulations! We are pleased to present you with the 2015 Microsoft® MVP Award! This award is given to exceptional technical community leaders who actively share their high quality, real world expertise with others. We appreciate your outstanding contributions in ASP.NET/IIS technical communities during the past year.
It’s an award not for exceptional technical knowledge as such, but rather for “community leaders..sharing .. with others”. I’m thrilled to receive it, and hope it will help me to do even more for the developer community in the future.
Next up I’m hoping to attend the MVP Summit in Seattle in early November. It will be great to meet many of the other MVP award recipients in person (and hopefully line up some speakers for the Adelaide .NET User Group).
It’s going to be busy over the next few weeks getting ready!
Yesterday and today I received some unusual calls on my mobile phone. They were both using computerised voices and claimed to be related to some legal action related to the “ATO” (presumably the Australian Tax Office). Yesterday’s call was supposedly from an “Agent John Smith”. Pretty sure the computer voice said “A-Toe”, rather than “A-T-O” too.
The calling numbers (and also the number they suggested I call them back on in the message) were:
The second number called twice as I didn’t hear or pick up the first time.
No surprises, it’s a scam - https://www.scamwatch.gov.au/news/telephone-calls-alleging-fake-arrest-warrants-used-to-scam-money
Interesting that they are calling my mobile – usually I get the “hello sir, your computer is sending us errors, would you like us to fix it” scams just on the home phone.
I had a good discussion the other day about a code warning that one of the new Roslyn Code Analyzers had flagged.
SonarLint comes from SonarSource, and has a whole bunch of analyzers, including this one: S3217 - "Explicit" conversions of "foreach" loops should not be used.
It is a useful warning, highlighting how the foreach instruction will cast each item for you if the collection of items is not generic. If you only use generic collections, you’ll probably never hit this – but if you ever have to deal with some of the older classes (such as the original ADO.NET types) then this may come up.
This got me curious. What does the IL (intermediate language) look like for a foreach.
The following C# code will trigger this warning:
var table = new DataTable();
DataRowCollection rows = table.Rows;
foreach (var row in rows)
We get this IL:
IL_0001: newobj instance void [System.Data]System.Data.DataTable::.ctor()
IL_0008: callvirt instance class [System.Data]System.Data.DataRowCollection [System.Data]System.Data.DataTable::get_Rows()
IL_0010: callvirt instance class [mscorlib]System.Collections.IEnumerator [System.Data]System.Data.InternalDataCollectionBase::GetEnumerator()
IL_0016: br.s IL_0026
IL_0019: callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current()
IL_001e: castclass [System.Data]System.Data.DataRow
IL_0027: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
IL_002c: brtrue.s IL_0018
IL_002e: leave.s IL_0045
} // end .try
IL_0031: isinst [mscorlib]System.IDisposable
IL_0036: stloc.s V_4
IL_0038: ldloc.s V_4
IL_003a: brfalse.s IL_0044
IL_003c: ldloc.s V_4
IL_003e: callvirt instance void [mscorlib]System.IDisposable::Dispose()
} // end handler
I’m no IL guru, but it you can get the basic idea – and sure enough you can see line IL_001e, there’s a castclass operation that’s run for each item in the foreach loop.
So in this case, you can’t just explicitly cast a DataRowCollection to an IList<DataRow>. The LINQ Cast<> extension method can be used though.
This code no longer triggers the warning:
foreach (DataRow row in rows.Cast<DataRow>())
And here is the corresponding IL:
IL_0047: call class [mscorlib]System.Collections.Generic.IEnumerable`1 [System.Core]System.Linq.Enumerable::Cast(class [mscorlib]System.Collections.IEnumerable)
IL_004c: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator()
IL_0051: stloc.s V_5
IL_0053: br.s IL_0060
IL_0055: ldloc.s V_5
IL_0057: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current()
IL_005c: stloc.s V_6
IL_0060: ldloc.s V_5
IL_0062: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
IL_0067: brtrue.s IL_0055
IL_0069: leave.s IL_0078
} // end .try
IL_006b: ldloc.s V_5
IL_006d: brfalse.s IL_0077
IL_006f: ldloc.s V_5
IL_0071: callvirt instance void [mscorlib]System.IDisposable::Dispose()
} // end handler
You can see there’s no more castcall operation, but instead notice line IL_0047. Now instead the code is calling the Cast extension method on the entire enumerable.
You might be wondering, does it make any different to performance? In this case not that I could detect. I loaded up a DataTable with 1,000,000 rows and compared execution times between the two approaches, and there wasn’t any significant difference between them.
This makes sense if you think about it – the cast needs to happen – either up front before the loop, or inside the loop. There’s no avoiding it.
So I’d say this is one warning that you shouldn’t necessarily just blindly follow. Having said that, if you’re iterating over the object more than once, then you probably will see a performance boost if you do the cast up front.
I’ve been pondering how to improve the ability of ADNUG (Adelaide .NET User Group) to do a decent job at:
- Skype/Google Hangout video conferences – so that the remote presenter can see and hear attendees
- Record audio of our group for a member with a vision impairment which means that they can’t physically attend meetings.
I’m not sure if there’s necessarily a huge overlap between those two requirements, but they both involve audio so they’re kind of related.
For the recent Google Hangout we had with Scott Hanselman, I purchased a Microsoft LifeCam Studio webcam. I mounted this on a tripod and used a couple of USB extension cables. Scott reported that the video quality was a bit poor with some flickering. I suspect the use of the extension cables might have reduced the quality of the signal too much – combined with the fact that I was only on Wifi instead of using the network cable (that I only noticed when the meeting was almost over!). The tripod mount is definitely a plus though.
Scott recommended the Logitech Webcam 930e, which has the advantage of being wider-angle (90° vs the LifeCam’s 75°). I’ll see how I go with the Microsoft camera, otherwise trading up might be an option.
Sound-wise was also not ideal. I didn’t have any complaints with previous hangouts earlier in the year with Jon Galloway and Sayed Hashimi, but maybe Scott was possibly more interactive and wanted to hear questions raised from and converse with the crowd. As it was, I had to repeat the questions for him (as I was standing near my laptop). So a microphone that can pick up the whole room would be great.
It seems the kind of microphone I’d need to pick up is a a conference or ‘boundary’ type. Most of these are ‘omni-directional’, meaning they pick up sound in all directions and from a wide area – contract that with a normal vocal mic, which works best right in front of your mouth.
For a USB solution, these models from MXL seem to be well regarded:
MXL AC404 USB Conference Microphone
MXL Mics AC-424 USB Boundary Microphone (MXL AC-424)
For an XLR connector (XLR is the 3-pin connector commonly used with professional audio equipment), then maybe something like this:
Samson CM11B Omnidirectional Boundary Microphone
The meeting we had this week at Marcellinas had over 40 people in attendance. It turns out Marcellinas function room has their own PA system, so I was glad to make use of that so that everyone could hear better. Having said that, they just have a hand-held microphone with no mic-stand – so that can get tricky if you’re speaking and trying to type at the same time.
Having a mic and loud speaker was a big help to the people in the room, but I didn’t have time beforehand to see if I could hook into their amplifier to record the audio. Instead to make the audio recording of the meeting, I just used the Windows 10 Voice Recorder app on my laptop (using my laptop’s inbuilt microphone), and just left that running for the duration of the talks.
A lapel microphone would be ideal, and wireless even better (so you’re free to walk around).
Audio2000 AWM-6032UL UHF Dual Channel Wireless Microphone System with One Handheld & One Lapel (Lavalier) Mic. This kit with a wireless hand-held and lapel would be pretty nice – wire up the main presenter with the lapel, which leaves the hand-held for the MC.
I get the impression that if you got the XLR-type microphones, you really need some kind of mixer/pre-amp that you’d then feed into the laptop (or other recording device).
Something like one of these:
So who knows if we ever get any of this. Given the costs, most of it’s probably just a pipe-dream. Having said that I’d appreciate any thoughts/suggestions/feedback on the options above or other ways that we might take some ‘baby-steps’ to improve things just a little bit.