Monday, October 25, 2010

IE9 first impressions

IE9's first beta has been out for more than a month, and I haven't written anything about it yet.This was in part because of lack of time, and in part because I did not want to say what can be said after using it for half an hour. Anyway, I'll give you some links if you really want to know that the Acid 3 score is 95/100, that on Windows 7 you can pin a site on the taskbar, that the user interface is cleaner than previous versions, that IE9 won't install on Windows XP.
What I want to focus on in this post is the feeling with this browser when used on a daily basis.
First, some background: my favourite browser is Chrome, I like it because it's simple, quick, clean.
So, I appreciate that IE9 has evolved in the same direction. In fact, I like IE9's minimalistic look, taken even beyond the level we've seen in Chrome: the tabs are on the same line as the address/search box.
This makes the space taken up by the browser above the page content as slim as Chrome in maximized mode (see image below), when tabs are allowed to use up all the space of the application 'title' bar (when Chrome is not maximized, it uses more space above the tabs, so that the user has always some blank space to drag around the application window). 
Browsing with IE9 is also simple, all essential features are at hand, all advanced features are one mouse click farther away.
As for speed, IE9 now seems to be able to compete with Chrome, some sites look quicker in IE9, some others (more) look quicker in Chrome. Anyway, speed differences are no more a clear argument against IE9. I'm talking about speed in general, not in any particular phase of the rendering process: there are very few fish tank sites in the Internet, I think as few as sites running ray tracing in JavaScript...
When it comes to using a browser daily, everything has to be smooth, and I think this is still not the case with IE9 beta 1.
First of all, autocompletion of login forms with data entered in previous sessions does not save as much mouse clicking and typing as in other browsers. Though annoying, this seems to be a minor issue that later releases are likely to fix.
More serious is the compatibility issue. You might expect that I'm talking about standards not yet implemented. Yes, there are many areas in Css3 where implementation is completely missing, and even some tests from the beta CSS2.1 Test Suite are failing (other browsers don't do better here, though). But for daily browsing these glitches won't have great impact.
I'm talking instead of standard implemented correctly in IE9 and sites that still treat IE9 like IE8 and its predecessors had to be treated... The Internet is full of pages that use clever tricks to have IE6+ behave the same way as other browser that implemented correctly web standards. Many of these are commonly used sites, Blogger, Facebook... There are many sites with styling issues, other with problems in scripts... Even if a relatively small percentage of sites has blocking issues, having to switch to a different browser is a pain that I'm not going to face. In some cases compatibility modes help resolve the issues, in other cases there is nothing to do. For these problems we cannot expect fixes from Microsoft. Fixes must come from site developers, that incorrectly include IE9 among the bad browsers from Redmond. For active sites this is likely to happen as sites are tested with the new versions of the browser, for sites that are published and not actively maintained this won't happen anytime soon, maybe never (a negligible loss, though).
The bottom line is that I find IE9 still not suitable for daily browsing, and it's a pity, because when navigating on sites where it does not have issues the experience is really smooth. IE9 is a nice browser, but it has to pay for its fathers' sins...

Monday, September 13, 2010

Browser war for good

There's quite much excitement for the coming beta version of Internet Explorer 9, due to be shown on the Beauty of the Web event in San Francisco.

IE and all other browser are all touted as the quickest, the most powerful, the nicest, the first in many areas of the browsing experience: hardware acceleration (IE9 here, FireFox here, Chrome here), javascript speed (IE9's figures here, FireFox's new engine here, Chrome's celebrations here), standard compliance (IE9 here).
IE9 is going to be a major release that puts Microsoft's browser on track to follow existing web standards; what's more important, it looks like Microsoft has abandoned the 'I'm the standards' position that made IE win the first browser war against Netscape, and was making it lose the second one.
Trying to maintain that position any longer would have made the world progressively shift to other browsers, as in fact is happening in the past few years.

Standard compliance is not going to make quick shifts in browser share: I, as a user, am not using Chrome for writing this post because it is more standard compliant than IE8, I'm using it just because it's quicker and cleaner. If IE9 is as quick and clean as Chrome I think I'll make it again my default browser.
It's when I wear my web developer hat that I feel the pain of having to test what I write on different browsers. And finding that most of the hacks are for one browser clearly explains why the developers/editors community cannot be happy with that browser. This sentiment can erode market share, because developers and editors do have some weight in directing users' choice.
During the first browser war standard compliance was not a must: competition was essentially between two competitors on one platform (Windows) based on features. This competition made available some rich features that are the ground for today's web applications: javascript, innerHTML, xmlHttpRequest... There was no space for standards, no time to wait for their definition before shipping new features.

Well, the first browser war was decided by features (probably an important role was played by the now much hated ActiveX technology) and by the inclusion in Windows so that anybody purchasing a windows box also had installed a copy of Internet Explorer.

If the first browser war had a clear winner, the 'peace' time that came after had a clear loser: the user. Subsequent versions of IE were more aimed to stabilize the codebase than to ship new features. Other minor browsers grew, also due to the fact that IE ceased support for Mac, and healthy web standard got developed, but very few new features got widespread.


Developers and editors could not make use of new features of browsers that accounted for small fractions of audience, if no alternatives were available in IE. Let's take for example Svg: a promising language, made soon available in IE through a plugin from Adobe, bur never supported with energy by Microsoft or Adobe. The result is that it could not be adopted as a widespread technology for producing rich content. If one had to deliver rich interactive content the only option was Flash. Now, with native support from IE9 (and from all the other major browsers, of course, but IE makes the difference) Svg can become a widely used platform to deliver rich content. The same can be said of Html5 and Css3. Unless support from IE is provided, you cannot adopt a new technology to give the user vital parts of the intended experience, or you lose most part of your target audience.

From the features IE9 is going to deliver, it looks like most IE users on Vista and Windows 7 are going to make the switch very soon after IE9's release to web. XP users should instead make the switch to another browser (IE8 is still good for the current web, but I bet new content will soon make it appear outdated).


With many different platforms out there (take into account also smartphones) a plurality of browser vendor is there to stay, and with Microsoft change in attitude they are all going to compete on standard compliance, and not against each other. That plurality will keep browser war going on. Whatever happens to browser market shares, I bet this time the winner is going to be the web.

Saturday, August 28, 2010

IE9 user interface leaked?

A screenshot of a user interface leaked is something of very little importance, but I'l take this as an opportunity to talk about the great news of IE abandoning a roadmap of halfway support of web standards vs existing sites designed for older versions of IE. As a web developer I am happy to see how in Microsoft they have finally changed their mind in deciding to support web standards. A 'I'm the standard' approach might have had some justification when there was no standard, and the web could only be viewed from a pc or a mac, but nowadays there are also other platforms (smartphones) that are becoming commonly used to surf the net, so the new approach of trying to be the best platform implementing and promoting good standards is the only viable.

Just to make life easier to those of you who are trying to guess where this guy writing stands in Browser War II (comments in today's blogs remind me of the first one between Netscape and IE), I'll tell you I have been using Chrome as my default browser, since its release, as I find it quicker and more modern than IE. I have installed and use also Firefox and Safari, to test the sites I work on. I have never been a fan of Firefox: I find it as ugly as IE, from a user's standpoint - though as a developer, I agree that nothing stinks like IE. I prefer Safari over Firefox. I have never taken Opera into account (I'm interested in browsers that users *are* using). As a browser user, I am falling back to IE only when Chrome lacks some features (no, I'm not missing ActiveX support!). And at last, I do not blame Microsoft for IE6 and its lack of standard compliance, I think they're to blame for not making today's shift in standard compliance back in IE7 days. I have seen what IE9 platform previews have delivered, and I think that if the user interface is going to be more Chrome-like I'm going to make the switch back to IE.

Coming back to the topic, another supposed IE9 user interface has leaked, as you can see from this image. Other supposed user interface screenshots that circulated earlier this year showed an oldstyle user interface, but this image seems to confirm other statements published recently in the blogs that anticipated how the user interface should look like. If this screenshot is real, it seems that at Microsoft they have followed the minimalistic design of Chrome that I really love, taking it a step further: they seem to leave more room to the content by putting all the browser's user interface in one single line (the tabs), using less space for inactive tabs (just the icon?). Another thing I hope to see in the new user interface is Chrome's 'status bar': in Chrome you see the status information while the page is being loaded, or a link destination as you hover over the link, then the status bar goes away to leave room to the content. In IE8 you still have to choose whether you want to see the status bar (and lose its space) or you do not want it (and lose the information).

Anyway, the user interface is not what I am eager to see. What I am really waiting IE9 for is standard support: in this area the technology previews have shown Microsoft is doing well. Microsoft is instead advertising the speed increases brought by GPU support, the only area where IE9 has a clear advantage, even over browsers running on a much more powered mac, as shown in the test published by Chris Foresman. In its IE9 Test Drive page Microsoft seems to suggest that browser speed is determined mainly by image intensive processing, as one could notice in the speed tests proposed in IE9 site. Ironically, IE9 might not be the first browser to implement GPU accelerated rendering in a release version: Chrome seems to follow suite later but more seriously than Firefox and Safari, and may ship before IE9 is RTM.

I think Microsoft is also doing well in browser speed: rendering engine, javascript speed, reuse of cached items are all areas that show significant improvements over IE8. But I think that rendering speed is still not so important as standard support: the good news with IE9 is that in the not so distant future we are going to see sites made for Html5, with no IE hacks, and at last write code once for all browsers. At first, we'll see many sites that do only skin-deep browser detection and treat any IE version the same way will render wrong in IE9 because now IE is standard compliant! But at the end the web will be a better place for everyone.


Wednesday, June 30, 2010

Control.Invoke and exceptions - part 2

This post is the second and last of a small series about Control.Invoke and its use when exceptions are thrown and handled. In the previous post we have seen that an exception loses its original stack trace and if you handle it in the background thread you cannot see any reference to the location where the exception was originally thrown.

Here is the same stack trace shown in the previous post:

at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
at System.Windows.Forms.Control.Invoke(Delegate method)
at TestForm.DoTheWork(Object sender) in C:\TestInvoke\Program.cs:line 36

Why does this happen? The stack trace only shows methods that run in the background thread... Well, this makes sense, because the exception is travelling through two stacks of calls: the first was the main thread, and the implementation of the Invoke() method rethrows the same exception so its original StackTrace property is cleared and only the stack of calls made in the background thread remains.

But the exception type remains the same, so why bother? Is the original stack trace so important? Well, in this case, not particularly... there's only one point in the application where a DivideByZeroException could be thrown. But what if our application and the call to the invoked method were more complex? What if the exception was a NullReferenceException? That stack trace information would be of much value, so let's try to figure out a way to preserve it. If we wrap the DivideByZeroException in another exception, in the method invoked, the stack trace of the InnerException (our DivideByZeroException) should be preserved. Let's give it a try: here is the example of the previous post, modified in the ThrowWithNiceStackTrace() method (the invoked method) so that the original exception is wrapped in a new ApplicationException:

using System;
using System.Windows.Forms;
using System.Threading;

static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new TestForm());
}
}

public class TestForm : Form {
private Button btn;
public TestForm() {
// Just add a simple button with a Click handler
btn = new Button();
btn.Text = "Click me";
btn.Click += new EventHandler(btn_Click);
this.Controls.Add(btn);
}

void btn_Click(object sender, EventArgs e) {
// We are creating a WorkItem to be run
// on a thread from the thread pool
WaitCallback wc = new WaitCallback(this.DoTheWork);
ThreadPool.QueueUserWorkItem(wc);
}

void DoTheWork(object sender) {
// This code is run in a background thread
try {
// We are using Invoke so the call
// to ThrowWithNiceStackTrace() runs in the main thread
this.Invoke(new MethodInvoker(
this.ThrowWithNiceStackTrace));
}
catch (Exception ex) {
Type ext = ex.GetType();
string stackTrace = ex.StackTrace;
}
}
private void ThrowWithNiceStackTrace() {
// This code is run in the main thread;
// calling Control methods is legal
this.btn.Text = "Clicked";
try {
this.ThrowWithLongStackTrace();
}
catch (Exception ex) {
throw new ApplicationException(
"Exception caught in invoked method", ex);
}
}
private void ThrowWithLongStackTrace() {
this.ThrowDivByZero();
}
private void ThrowDivByZero() {
int i = 1 / string.Empty.Length;
}
}

Now we run the sample and in the breakpoint inside the DoTheWork() method we see... the same result??

Yes, the exception thrown by Invoke() is still the DivideByZeroException. Not what you might expect, right? And obviously our precious stack trace information is lost again.

It turns out that Invoke() always throws the innermost exception. Digging through the System.Windows.Forms.dll assembly we can find that a call to Exception.GetBaseException() is made to retrieve the exception that will be rethrown. So not only the stack trace is lost, but also other exceptions we might have thrown to enclose the original exception and add context to it. How bad... this seems to be a bug in the Framework, and googling around we can find that we're not alone, and that at least there is some sort of confirmation of this being a bug in the Invoke method (see here, here and here).

What should we do, if we were interested in that information? Should we implement our Invoke strategy?

Hopefully not... the GetBaseException() method is defined virtual: let's try to fool this behavior, overriding the GetBaseException() method:

using System;
using System.Windows.Forms;
using System.Threading;

static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new TestForm());
}
}

public class TestForm : Form {
private Button btn;
public TestForm() {
// Just add a simple button with a Click handler
btn = new Button();
btn.Text = "Click me";
btn.Click += new EventHandler(btn_Click);
this.Controls.Add(btn);
}

void btn_Click(object sender, EventArgs e) {
// We are creating a WorkItem to be run
// on a thread from the thread pool
WaitCallback wc = new WaitCallback(this.DoTheWork);
ThreadPool.QueueUserWorkItem(wc);
}

void DoTheWork(object sender) {
// This code is run in a background thread
try {
// We are using Invoke so the call
// to ThrowWithNiceStackTrace() runs in the main thread
this.Invoke(new MethodInvoker(
this.ThrowWithNiceStackTrace));
}
catch (Exception ex) {
Type ext = ex.GetType();
string stackTrace = ex.StackTrace;
}
}
private void ThrowWithNiceStackTrace() {
// This code is run in the main thread;
// calling Control methods is legal
this.btn.Text = "Clicked";
try {
this.ThrowWithLongStackTrace();
}
catch (Exception ex) {
throw new InvokeException(
"Exception caught in invoked method", ex);
}
}
private void ThrowWithLongStackTrace() {
this.ThrowDivByZero();
}
private void ThrowDivByZero() {
int i = 1 / string.Empty.Length;
}
}
public class InvokeException : Exception {
public InvokeException(string message, Exception innerException)
: base(message, innerException) { }
   public override Exception GetBaseException() {
// Yes, we are lying: the doc says we should return
// 'The first exception thrown in a chain of exceptions'
return this;
}
}
When running this version of the program, if we stop at our breakpoint inside the catch clause of DoTheWork() we find that the exception caught is of type InvokeException, with this stack trace:

at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
at System.Windows.Forms.Control.Invoke(Delegate method)
at TestForm.DoTheWork(Object sender) in C:\TestInvoke\Program.cs:line 36

But now there is an InnerException of type DivideByZeroException, with the expected stack trace:

at TestForm.ThrowDivByZero() in C:\TestInvoke\Program.cs:line 60
at TestForm.ThrowWithLongStackTrace() in C:\TestInvoke\Program.cs:line 57
at TestForm.ThrowWithNiceStackTrace() in C:\TestInvoke\Program.cs:line 49

Not an elegant solution: we have to add a try catch in our methods called via Invoke(), at least in the methods where the location and nature of possible exceptions is not obvious. And we have to break the 'contract' of the Exception object: the implementation of GetBaseException of our InvokeException class will deliberately lie to callers. I know that lying is a bad thing (see Marcelo's recent post about this), but if we limit its usage to this workaround, we should be safe. It will also be easy to remove the workaround one day, when the fix to Windows.Forms is available: that day, just remove the InvokeException class and where compilation errors appear, there are the pieces of code to remove.

Less than nothing, anyway. I have used this workaround in error logs that we have in production, and I find it useful.


Control.Invoke and exceptions - part 1

Windows Forms in the .Net Framework are now becoming a bit outdated, but they are still widely used.

A common problem with their use is that long computations or tasks that involve gathering data from the web tend to freeze the user interface if executed in the main thread (more precisely, the thread that created the handle, and where form events are run). This impacts the user experience, so the common solution is to resort to background threads to do the hard work, and free the main thread to keep the application always responsive.

Using background threads used to be a tricky task, in Windows programming. Well, it still is, even if newer releases of the .Net Framework have brought tools such as the BackgroundWorker that frees the developer from handling much of the hassle while leaving him with full control of what's going on.

The most common issues involving multithreading in Windows Forms is that almost any call to all classes derived from Control must be done from the main thread. If you call a method from a different thread, and you are lucky, the IDE at runtime warns you that you are making an illegal call, but such problem may slip undetected into release, and then your code might even work as expected in 99% of the times... in the remaining 1% of the runs though your application will behave erratically, and you won't be able to discover why...

Here is a note in the Msdn documentation that remarks that nearly all methods of Control require to be called from the control's thread.

Note

In addition to the InvokeRequired property, there are four methods on a control that are thread safe:
Invoke
, BeginInvoke, EndInvoke, and CreateGraphics if the handle for the control has already been created. Calling CreateGraphics before the control's handle has been created on a background thread can cause illegal cross thread calls. For all other method calls, you should use one of the invoke methods to marshal the call to the control's thread.

A practical way to call methods in Control and derived classes, from your code that runs in the background, is to call Invoke() passing a delegate to the method you need to be called, and any arguments that you need to pass to the method.

The background thread will wait for the call to complete on the main thread, then your background thread will proceed; any return value of the called method is returned by Invoke(), so it can be used by your code. Even exceptions thrown in the method invoked are rethrown.

Everything seems to work fine, but let's make an example, and take a look at the stack trace of the exception:

using System;
using System.Windows.Forms;
using System.Threading;

static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new TestForm());
}
}

public class TestForm : Form {
private Button btn;
public TestForm() {
// Just add a simple button with a Click handler
btn = new Button();
btn.Text = "Click me";
btn.Click += new EventHandler(btn_Click);
this.Controls.Add(btn);
}

void btn_Click(object sender, EventArgs e) {
// We are creating a WorkItem to be run
// on a thread from the thread pool
WaitCallback wc = new WaitCallback(this.DoTheWork);
ThreadPool.QueueUserWorkItem(wc);
}

void DoTheWork(object sender) {
// This code is run in a background thread
try {
// We are using Invoke so the call
// to ThrowWithNiceStackTrace() runs in the main thread
this.Invoke(new MethodInvoker(
this.ThrowWithNiceStackTrace));
}
catch (Exception ex) {
string stackTrace = ex.StackTrace;
}
}
private void ThrowWithNiceStackTrace() {
// This code is run in the main thread;
// calling Control methods is legal
this.btn.Text = "Clicked";
this.ThrowWithLongStackTrace();
}
private void ThrowWithLongStackTrace() {
this.ThrowDivByZero();
}
private void ThrowDivByZero() {
int i = 1 / string.Empty.Length;
}
}

If you set a breakpoint in the DoTheWork method, inside the catch clause, you can see the stack trace property of our DivideByZeroException caught:

at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
at System.Windows.Forms.Control.Invoke(Delegate method)
at TestForm.DoTheWork(Object sender) in C:\TestInvoke\Program.cs:line 36

Hmmm... missing something? Wasn't our exception thrown in the ThrowDivByZero() method? There seems to be no trace of this in the stack trace!

But stay tuned, there's more to come...