Another Dumb Way to Start a Business Proposal

They just keep coming in.

Subject: re: advertising proposal

Hi,

I am a media buyer at Medios One LLC (www.mediosone.com).  I am interested in buying inventory on your site.  MediosOne is a global online advertising network.  We have offices in 5 countries and many more support offices around the world.  Our publisher network model gives us access to large amounts of high  quality inventory from all types of sites, which are targeted to users in many geographic locations. Some of the advertisers we work with include ICICI, Make My Trip, Max New York Life,  Zapak.com, Colgate, Hewlett Packard, Tata Sky, AOL, Citibank, and  India Times. We are  currently looking for publishers to add to our network. Currently, we are running a good  amount of campaigns targeted to the US, Asia, South America, UK as well as Western Europe.

Can you help me reach the appropriate person who handles advertising sales for your website?

If you are the correct person please let me know and we can move forward, if not would you please direct me to that person in your company.

I look forward to your response and the possibility of our companies doing business together.

Thank you,
Jobette Escobanas
contact information removed

This e-mail was actually relatively well written, and polite. They get points for that, as well as for targeting the global market and not just being limited to English and the good ol’ U.S.A. To nitpick his e-mail, he states his company’s name different ways: is it MediosOne, or Medios One? Also, why would I want Colgate ads on my website?

Maybe I’m old fashioned, but I think that details really do count on an e-mail like this. It’s obviously a copy-pasted e-mail with no mention of my name, my company’s name, my product’s name, the website address, or anything that tells me that the e-mail was targeted at me and not just blindly multicast to hundreds of other e-mails. To be honest, I’m at the point where any business deal I set up must be five figures per month and that’s not something I’m going to trust with just any drive-by e-mail with random spacing anomalies and other inconsitencies.

Also, Jobette has made an enormous faux paus in my book: He started the subject line with ‘re:’. Why did he do that? Does he think he has to trick me in to reading his e-mail by making me think this is part of an existing conversation thread? I don’t get it. Maybe it was a mistake, who knows. In any event, no thanks Jobette … but best of luck though I suppose.

Lastly, I apologize for not blogging much lately. I’ve been busy with work, social life, and of course Paint.NET work. And Rock Band. I’ve made enhancements to the PNG, BMP, and TGA codecs that have come with some refactoring work, as well as having extended IndirectUI to work with file type codecs/plugins. We were also tracking down a bizarre enumeration related bugs with the .NET runtime … I seriously thought my computer was failing and I”d have to buy new RAM, but then tracked it down to a smashed stack. Interesting stuff.

Paint.NET is going to get 8-bit and 24-bit PNG support

"It’s about time!!!" — Many users who keep pestering me for this

I just finished about 90% of the code for adding 8-bit and 24-bit support to Paint.NET’s PNG codec. Most of the work wasn’t even in the PNG codec itself, but rather in adding IndirectUI support for FileType plugins. Once that was done, the extra PNG code just tripped and fell into place. I just really didn’t want to write another WinForms widget complete with obnoxious layout and data binding.

(dang, I was trying to add a screenshot, but Windows Live Writer refuses to cooperate, oh well — I’ll save it for later I guess?)

To be honest, it’s that laborious and error-prone WinForms code that was preventing me from adding this support over the last 2 years. After you write it once you realize that you just don’t want to write and debug it ever again. With IndirectUI I only have to write the layout and data binding once, and then I can re-use it for every other file type configuration UI I make going forward.

I also plan to redo the configuration UI for the GIF, TGA, and DDS file types so that they use a few simple lines of IndirectUI instead of mountains of WinForms code. Who knows, maybe expanded BMP support will make it into the next release as well. Why not? I wish everything was as easy to implement as with IndirectUI.

Also, while implementing this I found out that the SOAP formatter for .NET serialization has essentially been deprecated. It doesn’t support serialization of types that have generic type parameters, and will not be updated … lame! So I have moved the persistence for file type settings over to the BinaryFormatter. This means that the next Paint.NET update will forget any settings you’ve had for file types. For instance, if you had JPEG set to a quality of 75 or something (default is 90), that will be reset in the next update.

Heterogeneous Catch Clauses for CPS Exception Handling

Well, that title is certainly a brain-full and won’t win me any search engine rankings for popular query terms.

Anyway, Nidonocu had an important question he posted on my previous post about the "Do" class:

This looks like this could be quite a useful class but I was wondering how this might work when it comes to wanting to catch specific exceptions rather than just the base Exception type?

I know from using FxCop that using ‘catch (Exception)’ is something Paint.net rather a lot and while I’m sure you sleep at night doing that, its something I’m trying to avoid in my own app. 😉 Are there any simple ways this code could be tweaked to not use Exception?

The issue is that the various TryCatch() helper methods only take a single delegate for the catch clause, and they always take the base Exception type. In essence, the burden of exception type filtering has been placed on that single delegate, forcing you to do something like:

Do.TryCatch(
    () => DoSomething(),
    (ex) =>
    {
        if (ex is InvalidOperationException) { … }
        else if (ex is SystemException) { … }
        else if (ex is FileNotFoundException) { … }
        etc.

    });

Even then, you can’t use "throw" to propagate the exception correctly. This may also encourage lazy exception handling that only covers the generic "oh no something happened" situation. We’re trying to simplify the code, darnit! You see, I knew about this problem, but I didn’t have a solution for it yet. The type of syntax that I wanted was this:

Do.TryCatch(
    () => DoSomething(),
    (InvalidOperationException ex) => { … }
    (SystemException ex) => { … }
    (FileNotFoundException ex) => { … });

This would be very nice and intuitive, and fairly succinct. You would expect the function signature for Do.TryCatch() to look like the following at this point:

void TryCatch(
    Procedure tryFn,
    params Procedure<Exception>[] catchFns);

But you run into a huge problem here. The C# compiler will try to convert each of the lambda expressions into Procedure<Exception> but will be unable to do so — it will convert the first one to Procedure<InvalidOperationException>, etc. and then spit out errors because it can’t convert it. (Actually, it will simply see that the lambda cannot be paired up with Procedure<Exception>, so that last sentence is a weird, technically incorrect simplification.) This is unintuitive at first, but makes perfect sense after thinking about it for a few minutes.

Even if two types, T1 and T2, have an inheritance relationship of T2:T1 (that is, T2 derives from T1), this does not create a relationship between Procedure<T1> and Procedure<T2>. For us, this means that even though InvalidOperationException derives from Exception and is thus substitutable for a parameter that is declared as taking an Exception, it is not the case that Procedure<InvalidOperationException> is substitutable for Procedure<Exception>. They are two distinct types in the .NET runtime. We are doing exception filtering, which is a different problem than just covariance or contravariance (I can never keep those two terms straight, I’m not sure which one applies here).

I was, however, able to set things up to my liking … almost. Here’s the syntax I was finally able to achieve:

Do.TryCatch(
    () => DoSomething(),
    CatchClause.From((InvalidOperationException ex) => CatchResult.Throw),
    CatchClause.From((SystemException ex) => CatchResult.Handled),
    CatchClause.From((FileNotFoundException ex) => { MessageBox.Show("Couldn’t find file!"); return CatchResult.Handled; }));

We are no longer passing a list of delegates to TryCatch(). Instead, we have a CatchClause class (aka functor) that implements a CanHandle() function to allow for filtering, and then a Handle() method that returns CatchResult.Handled to finish the catch clause, or CatchResult.Throw to re-throw the exception.

So, in order to effectively force a type relationship between the delegates (which cannot have "inheritance relationships"), we have to wrap them inside instances of class objects which do have that type relationship we want. In our case, we provide this relationship with a base class called CatchClause, which then has a derived CatchClause<TEx> class, where TEx has a constraint forcing it to derive from Exception. Then, we use CatchClause<InvalidOperationException>, CatchClause<SystemException>, etc. All of these are substitutable for the base CatchClause class, which lets our magic work. Finally, a static helper method in the base CatchClause class makes our TryCatch() usage easier to read and write. Unfortunately we cannot use an implicit type-conversion operator because those cannot take generic type parameters, and the type inference system isn’t quite psychic enough to enable it to work anyway.

Here’s the code, which I hereby release into the public domain:

public enum CatchResult
{
    Handled,
    Throw
}

public abstract class CatchClause
{
    public abstract bool CanHandle(Exception ex);
    public abstract CatchResult Handle(Exception ex);

    public static CatchClause From<TEx>(Function<CatchResult, TEx> catchFunction)
        where TEx : Exception
    {
        return new DelegateToCatchClause<TEx>(catchFunction);
    }
}

public abstract class CatchClause<TEx>
    : CatchClause
      where TEx : Exception
{
    public override bool CanHandle(Exception ex)
    {
        return typeof(TEx).IsAssignableFrom(ex.GetType());
    }

    public abstract CatchResult HandleT(TEx ex);

    public override sealed CatchResult Handle(Exception ex)
    {
        return HandleT((TEx)ex);
    }
}

public class DelegateToCatchClause<TEx>
    : CatchCla
use<TEx>
      where TEx: Exception
{
    private Function<CatchResult, TEx> catchFunction;

    public override CatchResult HandleT(TEx ex)
    {
        return this.catchFunction(ex);
    }

    public DelegateToCatchClause(Function<CatchResult, TEx> catchFunction)
    {
        this.catchFunction = catchFunction;
    }
}

public static void TryCatch(
    Procedure actionProcedure,
    params CatchClause[] catchClauses)
{
    TryCatch(actionProcedure, (IEnumerable<CatchClause>)catchClauses);
}

public static void TryCatch(
    Procedure actionProcedure,
    IEnumerable<CatchClause> catchClauses)
{
    try
    {
        actionProcedure();
    }

    catch (Exception ex)
    {
        foreach (CatchClause catchClause in catchClauses)
        {
            if (catchClause.CanHandle(ex))
            {
                CatchResult catchResult = catchClause.Handle(ex);

                if (catchResult == CatchResult.Handled)
                    break;
                else if (catchResult == CatchResult.Throw)
                    throw;
                else
                    throw new InvalidEnumArgumentException("catchResult", (int)catchResult, typeof(CatchResult));
            }
       }

       throw; // no one handled it, so rethrow
    }
}

"Use Paint.NET to Photoshop it"

I guess "Photoshop" really is turning into a generic verb, something that Adobe is undoubtedly unhappy about. I found this on a Q&A website, paraphrased for readability:

Question: "My friend has pictures of her eyes, a different color that really stick out. It’s grey and her eyes are bright blue or neon green. Please tell me how to do that." (Note: I believe they are asking how to take a picture of someone’s face and apply a grayscale effect to only the eyes.)

Answer 1: "Oh yeah, I’ve seen that but I don’t know how to do that either … let’s read what everyone else has to say, I want to know too…"

Answer 2: "use paint.net to photoshop it"

I won’t link to it so as to preserve their anonymity, but it’s easy enough to find by doing a search for the title of this blog post (including the quotation marks).

Anyway, I just thought that was curious enough to share … 🙂

More on C# Continuation-Passing Style: The Full "Do" class

Continuing on from yesterday’s post about simplifying exception handling code by using lambdas and continuation-passing style, I’d like to show off some other examples. Another common pattern in code is to generate a value, test it against some condition, and then have an if/else block to execute two other blocks of code dependent on that test.

So, let’s introduce the TryIgnore() and GenerateTest() helper functions with an example (see below for the trivial implementation). I want to generate a full file path for a log file, delete it if it exists, and then enable logging into that file for the later Windows Installer stuff that will be happening. However, if any of that fails I do not want an exception to be propagated because it isn’t critical to the success of what I’m doing.

Here’s the old code: (I’m omitting the code that initializes the tempPath, dwMsiLogMode, and dwMsiLogAttributes values. Assume that tempPath is just "%TEMP%", and the others aren’t really important for this discussion)

const string logFileName = "PdnMsiInstall.log";

try
{
    string logFilePath = Path.Combine(tempPath, logFileName);

    if (File.Exists(logFilePath))
    {
        File.Delete(logFilePath);
    }
}

catch (Exception)
{
    // Ignore error
}

try
{
    NativeMethods.MsiEnableLogW(
        dwMsiLogMode,
        logFilePath,
        dwMsiLogAttributes);
}

catch (Exception)
{
    // Ignore error
}

And the new code, which makes use of the TryIgnore() and GenerateTest() helper methods:

const string logFileName = "PdnMsiInstall.log";

Do.TryIgnore(() =>
    Do.GenerateTest(() =>
        Path.Combine(tempPath, logFileName),
        s => File.Exists(s),
        s => File.Delete(s),
        s => { /* no-op */ }));

Do.TryIgnore(() => NativeMethods.MsiEnableLogW(dwMsiLogMode, logFilePath, dwMsiLogAttributes));

There’s room to make the code even more succinct by inlining the value of logFileName into the Path.Combine() call, and to have an overload of GenerateTest() that doesn’t take an "ifFalse" delegate. Honestly though, I prefer to have my constants sitting in named values. It makes things easier when you’re sitting in the debugger and scratching your head and/or chin.

Here is the full code for my current "Do" class. I hereby release this into the public domain, so do whatever you want with it. There are obviously many other helper functions that could be added, but what I have her is sufficient to get things started. I’ll let you add others as you need them. And remember, my definition of Function has the type parameters in the reverse order that .NET 3.5’s Func delegate has them.

public delegate R Function<R>();
public delegate R Function<R, TArg>(TArg arg);
public delegate void Procedure();
public delegate void Procedure<TArg>(TArg arg);

public static class Do
{
    public static void GenerateTest<T>(
        Function<T> generate,
        Function<bool, T> test,
        Procedure<T> ifTrue,
        Procedure<T> ifFalse)
    {
        T value = generate();
        (test(value) ? ifTrue : ifFalse)(value);
    }

    public static bool TryBool(Procedure actionProcedure)
    {
        try
        {
            actionProcedure();
            return true;
        }

        catch (Exception)
        {
            return false;
        }
    }

    public static Exception TryEx(Procedure actionProcedure)
    {
        try
        {
            actionProcedure();
            return null;
        }

        catch (Exception ex)
        {
            return ex;
        }
    }

    public static void TryIgnore(Procedure actionProcedure)
    {
        try
        {
            actionProcedure();
        }

        catch (Exception)
        {
            // Ignore
        }
    }

    public static void TryCatch(
        Procedure actionProcedure,
        Procedure<Exception> catchClause)
    {
        try
        {
            actionProcedure();

        }

        catch (Exception ex)
        {
            catchClause(ex);
        }
    }

    public static T TryCatch<T>(
        Function<T> actionFunction,
        Function<T, Exception> catchClause)
    {
        T returnVal;

        try
        {
            returnVal = actionFunction();
        }

        catch (Exception ex)
        {
            returnVal = catchClause(ex);
        }

        return returnVal;
    }

    public static void TryCatchFinally(
        Procedure actionProcedure,
        Procedure<Exception> catchClause,
        Procedure finallyClause)
    {
        try
        {
            actionProcedure();
        }

        catch (Exception ex)
        {
            catchClause(ex);
        }

        finally
        {
            finallyClause();
        }
    }

    public static T TryCatchFinally<T>(
        Function<T> actionFunction,
        Function<T, Exception> catchClause,
        Procedure finallyClause)
    {
        T returnVal;

        try
        {
            returnVal = actionFunction();
        }

        catch (Exception ex)
        {
            returnVal = catchClause(ex);
        }

        finally
        {
            finallyClause();
        }

        return returnVal;
    }

    public static void TryFinally(
        Procedure actionProcedure,
        Procedure finallyClause)
    {
        try
        {
            actionProcedure();
        }

        finally
        {
            finallyClause();
        }
    }
}

Continuation-Passing Style Simplifies Your C# Exception Handling Code

Many lines of code in C# and other imperative languages are seemingly wasted by dealing with overhead such as exception handling and the like. How many times have you written the following type of code?

string[] fileNames;

try
{
    fileNames = Directory.GetFiles(…);
}

catch (Exception)
{
    // There was an error, like the directory isn’t there.
    // This isn’t an error for us, so just use a 0-length array
    // to simplify our later code
    fileNames = new string[0];
}

foreach (string fileName in fileNames)
{
    … do some processing on this file …
}

The basic pattern is, "try to obtain a value by calling this function, but if there’s an error then use a default value." It’s a lot of code, and it gets tiring and unreadable or unmanageable after awhile. This pattern, which is called the hole in the middle pattern, crops up all the time in imperative programming. The structure of this block of code is consistent, but there’s that little part in the middle that’s always changing. Most of the time we just trudge through the code because we want to get our stuff done, clock out, then go home and drink beer.

C# 3.0 adds a nice feature called lambda expressions, which is mostly syntactic sugar for anonymous delegates. Using them along with continuation-passing style we can write some helper functions that make this type of code much easier to deal with, and more expressive and succinct. In Paint.NET I’m adding a static class called "Do" that will help out with my code:

(Please note that Paint.NET’s "Function" delegate has the type parameters reversed from .NET 3.5’s "Func" delegate. "Func" delcares them in the traditional functional or mathematical ordering, where "F x -> y" is equivalent to "y F(x)". So, my code uses the "y-x" order. I added "Function" before .NET 3.5 added "Func", so let’s not get on my case about the ordering … 🙂 )

public static class Do
{
    public static T TryCatch<T>(Function<T> actionFunction, Function<T, Exception> catchClause)
    {
        T returnVal;

        try
        {
            returnVal = actionFunction();
        }

        catch (Exception ex)
        {
            returnVal = catchClause(ex);
        }

        return returnVal;
    }
}

(Quick digression: You’ll note that I do not assign to returnVal at the beginning of the function. This is a pattern I use quite often, because the C# compiler always does analysis to ensure a variable is assigned to before being used. This lets me make sure I always assign a meaningful value, and don’t miss the assignment in any of my branches or clauses. If I were to immediately assign "null", for instance, but then I forgot to assign a meaningful value to it in some if/else branch, then that error would go undetected.)

Once we have this utility function, the first code snippet simplifies to the following:

foreach (string fileName in Do.TryCatch(() => Directory.GetFiles(…), ex => new string[0]))
{
    … do some processing on this file …
}

Voila 🙂 I’m actually using this code in the setup wizard, as it needs to get a list of files in a directory and then delete them. If the directory doesn’t exist then there’s really nothing to do, but it also isn’t an error, and having the try/catch around the call wreaks havoc on the simplicity of the code. This lets me express that much more succinctly.

There are other patterns you can use, such as passing lambdas for the finally clause, or passing lambdas for various exception types, or even returning the exception for more imperative style processing.

How NOT to start a business "partnership"

Remember how I said I keep trying to write a blog post about bundleware, but I always get annoyed and it turns into rambling junk? (I mentioned this briefly in my previous blog post)

Well, I just received this email from Yazzle.net or something.

Dear Getpaint, [sic]

I represent Yazzle.net. My company is looking for new business partners to bundle our free bonus software. We want to pay you up to $0.80 for every download you bundle our bonus software with. We pay several of our partners over a thousand dollars a day. We offer products relevant to your site demographics. We believe that you can dramatically increase your revenue and simultaneously improve the experience of the visitors to your website.

Please give me a call at (phone number removed) to discuss or contact me at (removed) on aol instant messenger

Regards,
Joseph Ghartey
*Business Development
Yazzle.net
(contact details removed)

So apparently they’ll pay me "up to" $400,000 per month*. Err, tempting? But honestly, would I really want to do business with someone who thinks my name is "Getpaint?" Anyone who says they’ll pay "up to" a certain amount is probably just using that figure as a bait, and the real payout is probably 10% of that.** Although even $40,000/month is a nice figure.

When you download Paint.NET, you want and you get Paint.NET. I don’t think it’s appropriate to bundle Sudoku and ringtones, that’s just ridiculous to be honest. Plus, I refuse to do business with spyware/adware providers. I have more respect for weed dealers*** (well, as long as they’re like Nancy Botwin from Weeds on Showtime, anyway). If I ever bundle anything with Paint.NET it’ll have to be something that’s actually relevant and useful in the context of Paint.NET type stuff.

* Calculated from a rough average/estimate of 500,000 Paint.NET downloads per month.
** I have no facts to back this up, just good ol’ fashioned cynicism. I’d never heard of Yazzle.net before they e-mailed me.
*** This is not a pro-drug endorsement, I’m just trying to make a point. At least a weed dealer is providing something that the customer actually wants. Spyware/adware is usually snuck on to the user’s system without their honest consent.

Refactoring A Mountain: Late-Binding for Paint.NET v4.0

Like I stated earlier, I’ve finally started work on Paint.NET v4.0 (yay!). To that end, I’ll be focusing most of my development time throughout 2008 on this effort. There will still be Paint.NET releases in the meantime, as there is plenty of life left in the 3.xx architecture. There are a lot of small features that Paint.NET lacks and needs to catch up on that are feasible even without the changes I am slowly architecting into the 4.0 branch. I’m also hoping and planning to integrate some of the more popular or useful community plugins (with permission of course!).

A major change in the Paint.NET architecture for version 4.0 is the introduction of a pervasive late-binding and inversion-of-control mechanism. At a glance it looks like a localized version of COM: “give me an object that implements this interface, btw I don’t care what concrete class actually implements it” (actually, in COM you quite often do specify which implementation you want, but bear with me).

It isn’t anything revolutionary, but refactoring it into a code base that weighs in at 150,000 lines of code is a lot of work. It’s being very educational to me to go through and see all the poor code choices that have been made over the last 4 years. If only I had been psychic back then, I would have known the right way to do things! 🙂

Consider a line of code to load an image resource:

.     string labelText = PdnResources.GetString(“SomeDialog.SomeControl.Text”);

PdnResources is a static class that contains all the logic for retrieving the string resource from the appropriate language file. However, having this as a static class is a very very bad thing, and this pattern is repeated for many other classes that need to be accessible throughout the application. Any piece of code can load resources, even if it shouldn’t be able to. For example, there is code in the Layer and Document classes to load the default name for a layer, and this is not appropriate for code that is in the data layer of the application. This text should be supplied by whoever is creating the objects, or hooked in at the UI layer somehow instead.

To that end, this code will be moved out of a static class and into a public interface and a concrete, private implementation. A bindings provider (or scope) will serve as the mechanism for accessing it.

public interface IResourcesService { … }

internal sealed class ResourcesService : IResourcesService { … }

bindings.RegisterService<IResourcesService, ResourcesService>();

string labelText = bindings.GetService<IResourcesService>().GetString(
“SomeDialog.SomeControl.Text”);

At first glance, this may not appear to buy much, and is more code that is less expressive. But it allows me several things, including the freedom to move the resource loader, or to hide it from pieces of code (such as plugins, or from the data layer). I can do more granular versioning so that if plugins do need access I can at least continue to change it with more freedom (just introduce a “IResourcesServiceV2” or whatever). I can implement things like pseudo-localization by way of chaining together two implementations of IResourcesService. Logging and fault injection can be made easier, as they can also be implemented as a chained implementation. By “chained implementation” I mean that the normal implementation stays as-is, but a second implementation is registered so that it passes-through method calls while also performing some other service, such as logging or transformation. The primary implementation can then be kept clean and simple.

The “bindings” object would never be available globally or statically. Any object that needs to use it must take it via its constructor. This is proving to be a lot of work to enforce, but I believe it will be worth it. It makes it easier to analyze things like layering and dependency flow if code can’t just magically go and grab resources from static locations, and is instead forced to go through an object that is supplied by its creator/owner. For example, if I don’t want the data layer to be able to load resources, then I simply remove the IResourcesService from its bindings object. The only way to access the concrete class at that point would be via reflection, which is easy enough to detect and combat against.

I plan on extending this pattern to all of the static classes in the SystemLayer assembly as well. Instead of just bluntly calling into the PaintDotNet.SystemLayer.FileSystem static class, for instance, you would ask for the IFileSystemService via your local bindings provider object. The SystemLayer DLL would then have a static class with one function that would be responsible for registering all of the bindings.

This may even make things easier for Miguel de Icaza and his Mono port, Paint-Mono, although it’s too early to tell for certain. Done properly, there could be a PaintDotNet.SystemLayer.NetFxWin32.dll and a PaintDotNet.SystemLayer.MonoLinux.dll, and a simple configuration or command-line switch of some sort would choose which one to use at startup. I’ve paid attention to his blog posts and other documentation and it has brought to light some areas that still need to be separated into the SystemLayer DLL.

And while this could be a boon for Miguel, it’s also good for me and isn’t something I’m necessarily doing to directly help out his porting efforts. What if the differences between the XP and Vista code paths grew so great that I needed two different versions of the SystemLayer DLL? Or, what about a Mac OS version?* Moving to a late binding system and avoiding static classes will make things much, much cleaner. Who knows, maybe I can stuff Windows Forms itself behind an abstraction layer and decouple Paint.NET from it. That’s actually one of the things that the new IndirectUI system in v3.20 has allowed me to practice with: I could port the thing over to WPF or even to a console window, and the effects/plugin code wouldn’t know the slightest difference.

* This should not be taken as an announcement of a plan to release a Mac OS version.

Typo Bugs – OnScroll() versus OnShown()

I just recently fixed a bug in Paint.NET where I had inadvertently overridden the OnScroll() method instead of the OnShown() method. The code I added was meant to raise the priority of the UI thread while a dialog was initializing (in its constructor), and then drop the priority back to normal once the dialog was finally visible (in OnShown()). This was shown to improve the snappiness of Paint.NET’s UI because it does a lot of processing in background threads, which was then competing with dialog initialization and initial rendering. Since the reversion code was in OnScroll(), which never gets called, the reversion simply never happens. If I’d done a more careful code review, I probably would have caught this.

The reason it was in OnScroll() is because I typed “override OnS” and then expected Visual Studio to auto-complete the method signature. It did this correctly, but I had already overridden OnShown() and so the next match was OnScroll(). Luckily in this case there was no major negative consequence.

Quick Thoughts on Continuations for UI Code

Continuations in C#, as exposed via the yield keyword and “iterator blocks”, is a seriously underused and under-researched feature. In C++, you can use Win32 fibers to accomplish the same, and this is in fact how they are implemented in the .NET 2.0 runtime. Update: They are not implemented using Fibers. Thanks for the clarification James. Learn something knew every day!

Did you know that you can use these to implement blocks of code that can literally jump between threads? Quite useful for UI code so you can avoid using all sorts of tedious synchronization and messaging primitives, and also avoid having to split your tasks into multiple functions. Instead of writing function 1 which kicks off a task on the thread pool, then function 2 that performs the long-running task (load a file, download some data, compute something useful), and then function 3 that executes on the UI thread when that is done and sets some UI flags … you can write 1 function that is hosted by a dispatcher or executor of some sort, and then use “yield return” to spit instructions at it. Need to report progress? No problem. Switch to the UI thread, tell your ProgressBar control what’s up, then switch back to the background thread. “yield return new SwitchTo(Thread.UI)” and “yield return new SwitchTo(Thread.Background)” are going to prove quite handy for Paint.NET v4.0.

I’ve been experimenting with this concept a little bit, and the results are promising. I have a simple application that has a “AsyncImageBox” control that uses continuations. It has one function, “LoadTheImage” which implements all of the logic for establishing a connection with a server, downloading the image, reporting progress in the UI, and hooking up the final image to the UI. When the block of code needs to do something that must be done on the UI thread (report progress), it just switches over to the UI thread and does it. Then it reverts to the background thread. This is all inside of 1 function of code, there is no “queue this to the thread pool” or “invoke this message over to the other thread” or “wait on this mutex” or “set this signal” nonsense. I can use traditional synchronous/blocking code (aka, “easier to write, read, debug, maintain, understand, etc.”) for all of this.