Detecting a certain amount of violet in an image - follow-up
this.button2.Click += async (sender, e) =&gt;
{
    Task task = Task.Run(() =&gt;
    {
      ProcessImage(pictureBox1.Image);
    });
      Task.WaitAll(task);
      await task;
    };
}



Is the indentation like that in the original, or did it get corrupted by the tab-to-space conversion of StackExchange?

What's going on with the task? I don't know much about async event handlers, but as far as general async/await usage you only need one of Task.WaitAll(task) or await task.

What stops me from mashing the button and spinning off loads of tasks? Normally you would want to prevent a second click by opening a modal dialog (denying access to the button) or disabling the button, and then using ContinueWith to undo the block in the GUI thread when the task finishes.




    private void ProcessImage(Image image)
    {
        if (image == null)
        {
            return;
        }
        using (var selectedImage = new Bitmap(image))



If the image is already a bitmap, this is unnecessary and slow. It's probably worth having two cases and factoring out the code which works with Bitmap to a separate method:

    if (image is Bitmap) Process(image as Bitmap);
    else using (var bitmap = new Bitmap(image)) Process(bitmap);





            double total = 0;
            double infected = 0;



That's an odd choice for counters. Why not use an integer type and coerce to double when dividing?




            for (int x = 0; x &lt; selectedImage.Width; x++)
            {
                for (int y = 0; y &lt; selectedImage.Height; y++)
                {
                    selectedPixel = selectedImage.GetPixel(x, y);



This is slow. A loop over GetPixel is always slow, and it's worse when the outer loop is over x because you lose cache locality. If you care about speed, use LockBits and switch the loops.




                    if (selectedPixel.GetHue() == (violet.GetHue()))



GetHue() returns a float. == comparisons on non-integer numeric types are generally inadvisable. You should almost certainly test whether selectedPixel.GetHue() is within a small distance of violet.GetHue(). How wide a range is a parameter which you may need to tune to get the results you expect.




                if (Double.TryParse(Convert.ToString(percentage).Substring(0, 6), out result))



??! Why? And if the specs require you to round to an exact number of decimal places and that's non-negotiable, why use double instead of decimal?




            catch
            {
                MessageBox.Show("No Violet Pixels Whatsoever were found");
            }



Under what circumstances can this catch anything? The only one I can see is if total == 0, in which case the error message should really be that the image was empty.




            finally
            {
                selectedImage.Dispose();
            }



This is unncessary: it's already in a using statement.