AppDomain.UnhandledException Part 1

Mon, December 20, 2004, 03:49 PM under MobileAndEmbedded
The punchline is that the AppDomain class (along with other enhancements such as AppDomain.Unload), also offers AppDomain.CurrentDomain.UnhandledException. As soon as I saw that (in combination with this), I started running various tests (over 20 different combination scenarios run in release mode with no debugger attached) in order to update an older post on Global Exception Handling on the CF 2.0.

Let's remember that unhandled exception tests must include: Throwing on the GUI, on a ThreadPool thread, Thread, Control.Invoke, object finalizer and after Application.Run when the app is exiting. As you recall, on the desktop the only way to cater for all of these is by hooking into AppDomain.UnhandledException, Application.ThreadException and surround Application.Run with try..catch. CF 1.0's limitation was fully described here.

With NETCF 2.0, we still don't have Application.ThreadException but, unlike the desktop scenario, we don't need it since the NETCF 2.0 AppDomain.UnhandledException catches *all* unhandled exceptions. Here is an example of its use:

static class EntryPoint {
[MTAThread]
static void Main() {
// Add Global Exception Handler
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(OnUnhandledException);

Application.Run(new Form1());
}

// In CF case only, ALL unhandled exceptions come here
private static void OnUnhandledException(Object sender,
UnhandledExceptionEventArgs e) {
Exception ex = e.ExceptionObject as Exception;
if (ex != null) {
// Can't imagine e.IsTerminating ever being false
// or e.ExceptionObject not being an Exception
SomeClass.SomeStaticHandlingMethod(ex, e.IsTerminating);
}
}
}


Note that I have never seen e.IsTerminating be false, in other words after your handler gets run the process exits. The last statement includes the case where you throw an exception in the handler; so, exceptions thrown in the global exception handling routine are swallowed (why would you throw in there in the first place is a valid question).

Next entry will serve as a holder of the VB equivalent code plus a blurb on try..catch around Application.Run. Go :-)

I stripped this article from the fine detail and instead just presented the result; if you have a deeper interest let me know and I'll send you how I arrived at the conclusions.

Blog link of the week 51

Sun, December 19, 2004, 01:36 PM under Links
The worst thing that can happen to me from a BLOTW perspective is this: a good post appears on a Monday so the people focusing on link blogging have already told the world about it. Given my BLOTW policy, that eliminates it from my shortlist for Sunday's BLOTW entry. This week I was lucky :-)

If you haven't already, go read why going to the bathroom will help you understand threading (Monitor.Xxxx methods) (long)

I can't help making a NETCF observation here. We only have Monitor.Enter/Exit in CF 1.0; CF 2.0 adds TryEnter but that's it, no Pulse methods :-(

StackTrace

Sat, December 18, 2004, 02:56 AM under MobileAndEmbedded
If you are a desktop developer, imagine life without Exception.StackTrace. Has it sunk in yet? Good, your imagination has just taken you to what is reality for CF developers today (add to that CF's absence of GEH and you'll realise why it is the *compact* framework).

If you are a CF developer you feel my words no doubt... well feel no longer, because CF 2.0 (available now in a CTP release near you) gets Exception.StackTrace :-D

Before you ask, no the standalone StackTrace class is not available and neither is Environment.StackTrace but you can't win them all right?

As you'd expect, the built-in CF error dialog that comes up when an uncaught exception is thrown, now takes advantage of StackTrace to give us better info as to where the unhandled exception occurred.

November CTP

Fri, December 17, 2004, 02:01 PM under Whidbey | VisualStudio
As you should be aware by now, there is a November CTP out (I learned about it here). Thought I'd briefly share some experiences on the sleek VS2005 Standard Edition.

The install went though OK, including launching VS. Creating a project was not so smooth though; some error about System.XML being corrupt. Repaired the installation and tried again: bingo! So now I do my usual thing of creating one of each Windows App and NETCF app (in both C# and VB) to see if it is worth continuing and yes, it all worked. Then turned my focus to CF projects only (if you are asking "why", welcome to my blog :-).

First noticeable omission compared to the Beta 1 (the October CTP escaped me), is Deploy to My Computer! Where has it gone? That was way cool (previously mentioned it in passing here - penultimate paragraph) and I hope it will come back before Whidbey RTMs. UPDATE: If you also want this feature back, GO VOTE FOR IT NOW (it has been cut and is not on the list for RTM.

Looking into the above further, I actually try to execute a CF exe on the desktop and it fails to find the right assemblies (exception and death). This also worked before and works today with VS2003! So I move the exe to the actual directory where the CF assemblies are, and now it works... interesting.

Major setback now: I cannot debug with the emulators (I am running XP in a VPC). This worked in Beta 1, so it is either a step backwards or something wrong with my installation. Just running up the emulators works fine, by the way. Taking that last step further, I decide to manually copy the exe to the emulator (even a plain deploy with VS doesn't work). I can now run the exe and have a play with it (after also copying the CF 2.0 cab and installing it, of course). BTW, sharing files is made much easier with the direct option to have a "Shared Folder" in the options of the emulator; it then appears as "Storage Card" in the image. UPDATE: Got emulator debugging working with thanks to Amit Chopra (Brian Chamberlain really).

Next thing to examine are the NETCF framework assemblies in ILDASM (yes I like Object Browser and other tools but I prefer exploring what's new through ILDASM - call me crazy). I like what I see, but this is not the purpose of this blog entry. I find a couple of areas of particular interest and decide to drill into them (as in look at the implementation of the methods). No IL!!! All methods have a code size of 1, which is the ret statement. What's going on here? I open the CF assembly I just created and, sure, I can see the IL fine. Also fine are the desktop framework assemblies. I must be missing something here but I have never encountered this before, so if anybody has any clue please share. UPDATE: Turns out with this release the CF assemblies on the desktop are just designer shims and have no real code in them; the workaround for examining non-publics and implementations is to copy the files from the device to the desktop and disassemble them - thank you to Mike Zintel and his team for pointing this out. BTW, if you don't fancy copying the files and can cope with unfriendly file names, just extract the appropriate cab files directly on your PC :-)

I'll update this entry with any relevant info, but that's all for now. Next time we'll see a cool addition to CF 2.0 that was not in the Beta. At some future date I will cover Generics, which are also available in this build.

Stopwatch

Thu, December 16, 2004, 01:03 PM under MobileAndEmbedded
A useful class in .NET 2.0 for measuring performance, but not only, is the System.Diagnostics.Stopwatch class. Once again this does not appear to be part of CF 2.0, so I set out to implement one for both CF 1.0 and desktop version today (.NET 1.1) and tomorrow (CF 2.0).

You can download the dll from here (so you get the BackgroundWorker as a bonus) or get the code at the end of this entry.

The interface is very simple:
1. Create an instance of a Stopwatch class.
2. Start it and stop it at will, or reset it back to zero.
3. At any moment in time, access one of its Elapsed properties (returning TimeSpan, milliseconds or ticks)
4. You can check if an instance is running

There are also a bunch of static (Shared in VB) calls you can make:
5. If you are lazy and want a new already started Stopwatch with one call, use the StartNew static method
6. If you just want to know the current number of ticks in the timer mechanism, call the static GetTimeStamp
7. The number of ticks per second is accessible via another static: Frequency

Cannot get much simpler, can it :-) In addition, on MSDN you can find: .NET Client Stopwatch Application Sample

My implementation uses the high resolution QueryPerformanceCounter/Frequency APIs. If they are not supported on your device, you will get an exception when creating a Stopwatch [note that the .NET 2.0 version copes with a fallback mechanism, I have not implemented that]. If you are the unfortunate owner of such a device then I suggest you use Environment.TickCount.

Download the DLL here
Download the VB code here
Download the C# code from OpenNETCF

Blog link of the week 50

Sun, December 12, 2004, 03:18 PM under Links
Regular readers know by now that I would not talk about some conference that is 10 months away or some autocomplete search feature (in the same way I will not be talking tomorrow about yet another desktop search feature).

Did you think that "GC" and "leak" could exist in the same sentence? Apparently they can.

To balance things out, go to this not so technical post about MSFT shipping practices/processes.

Finally, take a seat back and enjoy the arguments discussions between one of the 3 amigos and the respectable opposition (if ever I needed proof that MSFT recruitment works well, I got it when they hired some of the best UK UML/methodology minds - all they need is this guy and they'll be flying).

Multifile assemblies in CF 2.0

Thu, December 9, 2004, 04:05 PM under MobileAndEmbedded
A question came up in the ng, and my reply included the statement "CF 1.0 does not support multi-module assemblies [...]". So I thought I'd check to see if that changed in CF2.0. The short answer is "yes, they are supported"! If you are on the CF team, please let me know why you are offering this feature. What was the driver for it? Anyway, read on to see an example of multifile assemblies in CF 2.0.

If you don't know about multi module/file assemblies, I suggest you search the web for definitions, as I am not going to describe the principles (the feature is available in the .NET full framework today). In a small nutshell, you compile code in modules (.netmodule extension and nothing to do with VB's module) that you can link to from an existing assembly. (Alternatively, using al.exe you create an assembly that holds the manifest only and references the real code in one or more netmodules).

So here is how to do it with CF 2.0

1. Create a ProgramMixed.cs file with this code in it
namespace MixedLanguages {
static class Program {
[System.STAThread]
static void Main() {
System.Windows.Forms.Application.Run(
new MixedLanguages.Form1());
}
}
}

2. Create a Form1Mixed.vb file with this code in it
Namespace MixedLanguages
Public Class Form1
Inherits System.Windows.Forms.Form

Public Sub New()
Me.Text = "Run from Csharp code"
Me.MinimizeBox = False
End Sub
End Class
End Namespace

3. In the command line type the following (assuming you have all the PATH variables set and you are pointing to the right directories):


vbc /netcf /noconfig /nostdlib /r:"E:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\CompactFramework\WindowsCE\mscorlib.dll","E:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\CompactFramework\WindowsCE\System.dll","E:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\CompactFramework\WindowsCE\System.Windows.Forms.dll" /t:module Form1Mixed.vb


You should get a Form1Mixed.netmodule file created (note that /sdkpath crashes with Beta 1).

4. Also type this:


csc /noconfig /nostdlib /r:"E:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\CompactFramework\WindowsCE\mscorlib.dll","E:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\CompactFramework\WindowsCE\System.dll","E:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\CompactFramework\WindowsCE\System.Windows.Forms.dll" /addmodule:Form1Mixed.netmodule ProgramMixed.cs


You should have a ProgramMixed.exe created.

In both successful command line compiles, the output looks something like this:

Microsoft (R) Visual Basic .NET Compiler version 8.0.40607.16
for Microsoft (R) .NET Framework version 2.0.40607.16
Copyright (C) Microsoft Corporation 1987-2003. All rights reserved.


5. You now have 2 files. Copy them to your device or the emulator and run the exe (in fact, since they are retargetable, you can run the exe on the PC as well). That's it!

So, apart from the ability to mix languages without having to create separate dlls, what is the advantage of multifile assemblies? I am not sure. Maybe the search you did earlier has given you the answer, in which case let me know. There are some benefits listed here (and an example).

I would be much more excited if we could actually statically link the netmodules into a single file. This becomes reality in VS2005 on the desktop, but only for C++.

UPDATE: Turns out we can merge the netmodule into a single exe file.

.NET CF MVP Chat

Thu, December 9, 2004, 11:28 AM under MobileAndEmbedded
I've blogged before about the SDP chat. Today it was the MVP's turn to host the monthly chat. These are not MSFT employees and therefore the format of the chat is more of a troubleshooting session; there isn't much opportunity of obtaining official info on future features, etc. As always the experts got a standing ovation in the end.

So, once more, update your calendars with the chat dates you are interested in or keep missing out!

BackgroundWorker for CF 1.0

Mon, December 6, 2004, 10:50 AM under MobileAndEmbedded
TIP: Download the class at the bottom of this post

.NET 2.0 makes threading easier by offering a BackgroundWorker class (not sure if CF 2.0 will have it, though). Read on to find out how to take advantage of it today in the CF 1.0 (also works on the desktop .NET 1.1).

The beauty (for someone not into documentation like me) of implementing a desktop class for the CF is that you don't need to document its usage (to an extent). There are already MSFT samples (and others) for the full Fx's class, so all you have to do is preserve the interface and behaviour.

So this is my summary of the BackgroundWorker story with hyperlinks to msdn.

In its simplest:
1a. Create an instance of the class (new BackgroundWorker())
2a. Hook up to its events (DoWork, RunWorkerCompleted)
3a. Tell it you want to do some background work (RunWorkerAsync)
4a. It raises the event. In your DoWorkEventHandler method do your background stuff (without touching GUI of course)
5a. When done, your RunWorkerCompletedEventHandler method will run on the GUI

Let's add value [Pass state in, cancel from job]:
3b. Optionally pass an object to the worker method (RunWorkerAsync, DoWorkEventArgs.Argument)
4b. Optionally decide in your background work to cancel (DoWorkEventArgs.Cancel=true)
5b. In your RunWorkerCompletedEventHandler method, check whether the operation was cancelled (RunWorkerCompletedEventArgs.Cancelled)

It gets better [Get a result back]:
4c. From your background work, optionally pass a result to the GUI when it's finished (DoWorkEventArgs.Result)
5c. Check for it (RunWorkerCompletedEventArgs.Result)

Wait, there is more! [Progress notification]
2b. Additionally hook up to a progress event (ProgressChanged) if you configure the object to allow it (.WorkerReportsProgress)
4d. From your worker method, let the object know the percentage (ReportProgress) optionally passing some state (ReportProgress)
6. In your ProgressChangedEventHandler method that runs on the GUI, check the percentage (ProgressChangedEventArgs.ProgressPercentage) and optionally the state given (ProgressChangedEventArgs.UserState)

Finally [Cancel from outside the job]
2c. Optionally Configure the object to allow cancellation (WorkerSupportsCancellation) other than just from the background worker method itself
4e. In your worker method check periodically if a cancel has been issued (CancellationPending) and if it has proceed as 4b
7. From any place in the code, ask the worker to cancel (CancelAsync)

If you have VS2005 just drag and drop it from the toolbox and start playing with it (on the desktop, not the CF). Browse its interface in object browser (it is under System.dll in the System.ComponentModel namespace)

Also read:
How to: Run an Operation in the Background
Walkthrough: Implementing a Form That Uses a Background Operation (Highly recommended)

Note that with my CF implementation you cannot drag the component on a form, but instead you have to manually create it from code (the assumption being you will do that from the GUI thread).

Download the DLL here (works on all platforms/versions)
Get the VB source here
Get the C# source at the next drop of the SDF

UPDATE: Also read this comprehensive BackgroundWorker sample

Blog link of the week 49

Sun, December 5, 2004, 02:16 PM under Links
Where did you read about yet another CTP, new spaces for blogs, unit testing software release, the number one word for 2004 and an antisapm screensaver? ...not here...

Brad Adams shows how to validate parameters in security-sensitive operations; I would have never thought of that and probably still won't ever use it..how about you?

I bet you can't sleep at night [:-)] not knowing why Windows run the timer at 55ms

Go back to basics with a performance analysis of the ArrayList