C# UI – Cross Threading exceptions

This WPF form invites you to click a button, at which point text appears in the box:

WpfAsync01

WpfAsync02

Press [Button]…

WpfAsync03

Fine. (Sorry, I see I left the redundant Delegate reference in the screenshot above –  please consider it removed – it is correct in the PasteBin.)

If we now make the call to the edit asynchronous, then in debug mode in Visual Studio, we get a nice big exception:

WpfAsync04

WpfAsync05

{“The calling thread cannot access this object because a different thread owns it.”}

So a cross-thread exception because the worker thread is trying to access controls which belong to the UI/thread. Good. PasteBin. Having above run it as Debug/F5, I then ran it NoDebug/Ctrl F5, naively thinking it would somehow (?!) still expose the expose the exception at runtime. Well, an additional screenshot will add nothing, because when you click the button, the input screen just sits there, happily accepting the key presses, and on the face of it, doing nothing about it. I need to add some code that flags the exception somewhere. You might have thought that a .Net application runtime error might flag an exception to the event log… but again, why would it? If it did that every time on your average Windows box, I suspect you would soon run out of disk space. So you need to explicitly write to the event log, assuming you decide that is where you want your exceptions to be written. If this was a proper application, then you might create a dedicated event log type… but I’m just going to use Application. The code changes to use System.Diagnostics:

WpfAsync06

PasteBin

WpfAsync07

That is all good: the exception is persisted to the Event Log, but we now have failing code. The solution is to ensure that we only try to update the control when it is on the main/UI thread, and not on the worker thread. This is done in WPF by testing for (control.)Dispatcher.CheckAccess(). (Forms is certainly different, and Universal Apps and Silverlight might be different.) If it is true, then we are on the UI thread. If it is false, then we instantiate a new version of the delegate and call it on the UI thread via the Dispatcher, recursively calling back into the delegate implementation. WHA??!! I think your best bet is to set a breakpoint as I have shown here, and step into (F11) to understand what sequence it follows. You might notice that on subsequent executions, it is already on the UI thread. That feels weird, so maybe I did something wrong. I don’t think it matters, as the code works. And if you exit the app and start again, you’ll see it starts off again on the worker thread.

The result:

WpfAsync08

, and the code:

WpfAsync09

There is nothing in here that justifies the use of asynchronous behaviour. You will just have to take my word that when you do have a use-case, this will help.

Visual Studio: diagnostics

I am a fan of the debugger in Visual Studio. For a number of years now, I have seen the Intellitrace window appear more as an irritant… because I knew nothing about it. So today I took the trouble to watch the VS-embedded video on this. And it sounds promising, particularly the ability to run Intellitrace on a machine that does not have VS, and to collect the data for subsequent analysis on a machine that does.

The diagnostics section of the MSDN blog:

Channel 9 Visual Studio videos, including the Intellitrace one.

Snippets: C# console app

If I want to play with some ideas in C# that don’t involve a GUI but where you want some console output, then that’s obviously a use-case for the Console Application template in Visual Studio… but it’s not quite as I like. THIS is as I like:

ConsoleApp01

Pastebin

That then gives me a clear place in the RunTheTest method to new up stuff, and a ready-made prompt so the console doesn’t just run away after execution.

While I’m on it, this will save me a few keystrokes * 1000, as it’s easier to remove stuff doing this crude form of debugging than it is to add it. I always like to surround arguments in those square brackets for easy visual delimitation, better too many than too few:

ConsoleSnip01

Of course I should anyway go back to my Resharper Template notes here, and the related YouTube video here.

.Net: debugging teeny tiny console apps

I had the world’s simplest console app in C#, and I could not figure out why I could not debug into it. Sure, it was a Release config, but as Any Fule Doth Know, as long as you have the matching .pdb, then you can debug, even in Release.

Here is my code, with breakpoint set, in Release mode, running as Admin. All the debug defaults are on in the right way (I know what I mean):

debug01

I’m running this from PowerShell, also as Admin. The bin folder after the build:

debug02

Fine. Let’s attach. See what likely candidates we have…

debug03

“powershell.exe” That surely has to be it. There’s no DebugAsRelease.exe in there, so it must be “powershell.exe” (not least because I can’t find any other obvious candidates). I’ll attach to that, and run the program:

debug04

debug05

Oh, I must be running from the wrong place, or my PDBs are out of step, or it doesn’t like PowerShell… yada, yada, yada. I even tried SysInternals for clues. Nothing.

As you are clevererererer than I, you will doubtless have twigged long ago my Doh moment. I needed to give the debugger a chance to attach to the right thing. As things stand, the program is so trivial is just rushes through before we have a chance to attach. Well, I dare say I could listen for a, yes, DebugAsRelease.exe appearing in the list of available processes, but I want to keep things really simple.

The, or at least a, solution is the yellow highlight below:

debug06

If I now a) start the program running, b) NOW look for the process and attach…

debug07

… then c) hit return  in the console app (ie invoke the ReadLine), then our Doh moment is replaced by a Tada moment:

debug08.

, and we can all go home. Actually, I am at home.

(Later…) You would never do the above, well unless you have a functional reason to do it… and opinions seem to vary on conditional compilation. But here it is, regardless. In this snippet, don’t think that the debugger magically spawns itself: you still have to attach to it to get it to rest on line 18:

debug09