1

I'm working on a program that can contain all the programs and games that you add to the program, so you can have it all in one place. The program also has a search feature.

The problem is that the program takes a while to load the first time you run it, or after you restart the computer. I am pretty sure it is because I use Icon.ExtractAssociatedIcon to get the icon from the executables.

So if there is a lot in the XML file (I save data in an XML file) then it takes a while to load the program because i extract the executable icon.

I made a method to make it easier for me:

public static BitmapImage GetExeIcon(string path)
{
    try
    {
        using (MemoryStream memory = new MemoryStream())
        {
                    System.Drawing.Icon.ExtractAssociatedIcon(path).ToBitmap().Save(memory, System.Drawing.Imaging.ImageFormat.Png);
                    memory.Position = 0;
                    BitmapImage bitmapImg = new BitmapImage();
                    bitmapImg.BeginInit();
                    bitmapImg.StreamSource = memory;
                    bitmapImg.CacheOption = BitmapCacheOption.OnLoad;
                    bitmapImg.EndInit();

                    return bitmapImg;
        }
    }
    catch (Exception)
    {
        MessageBox.Show("Are you sure it is a valid exe path?");
    }

    return null;
}

I will admit, there's some of the stuff in the using blocks i don't understand, but i try to understand it as much as i can.

Load method:

public void Load()
{
    if(File.Exists("ApplicationSaves\\apps.xml"))
    {
        using (XmlReader xmlReader = XmlReader.Create("ApplicationSaves\\apps.xml"))
        {
            string name = string.Empty;
            string desc = string.Empty;
            ApplicationItem.AppType type = ApplicationItem.AppType.Game;
            string exePath = string.Empty;

            while (xmlReader.Read())
            {
                switch (xmlReader.Name)
                {
                    case "Name":
                        name = xmlReader.ReadElementContentAsString();
                        break;
                    case "Description":
                        desc = xmlReader.ReadElementContentAsString();
                        break;
                    case "Type":
                        type = (xmlReader.ReadElementContentAsString() == "Game" ? ApplicationItem.AppType.Game : ApplicationItem.AppType.Program);
                        break;
                    case "ExePath": //This is the last data it needs
                        exePath = xmlReader.ReadElementContentAsString();
                        GlobalManager.applicationList.Add(new ApplicationItem() { Name = name, Description = desc, ExePath = exePath, Type = type, Icon = GlobalManager.GetExeIcon(exePath) });
                        break;
                }
            }
        }
    }
}

You can see i use GlobalManager.GetExeIcon(exePath) in the case "ExePath" at the very end, so it does it to all the items it add

Last picture you can see what i use the icons for :-) Do you have any advice how i could reduce load time? I know i can save the extracted icons to a folder and load them from there if they exist, i guess that will reduce the loading a little. But if you know a better way, i will appreciate it :-)

Some of the saved data in the xml

Main window of the app, you can see what i use the icons for

PS. Sorry if it is too much to read, i'm always trying to be specific, but with a lot of text. Please tell me if you need more information.

You don't have to read the stuff below, but maybe someone that reads it has some advice:

I won't say i'm new to C#(i started about 2 years ago) or programming in general. 2 years with C# and i still don't know how/when/why to use structs, interfaces, and other cool stuff.

I've been taking long breaks sometimes because i didn't know what i should do, and losing motivation because i felt i was learning nothing after many months(I still do lose motivation sometimes because i feel i'm not good enough or not learning)

Jesper
  • 402
  • 5
  • 10
  • 4
    I would recommend making things asynchronous and loading them in the background, then updating the UI as things get pulled in. If you're unfamiliar look into [async/await](https://msdn.microsoft.com/en-us/library/hh191443.aspx) – Michael Sep 18 '15 at 14:16
  • 2
    First off before guessing what MIGHT be time-relevant and making huge refactorings and improvements that will serve in only 10% load-time-improvement you should consider using a profiler such as DotTrace. I bet the loading of the icon isn´t the actual problem. – MakePeaceGreatAgain Sep 18 '15 at 14:20
  • 2
    I agree with @HimBromBeere; I am wrong probably more than a third of the time when I try to guess what is slow and how slow it is. Use a profiler, make a change, and then profile again to see if it worked. Set a performance goal and use good engineering discipline to meet that goal; don't try random stuff until it works. – Eric Lippert Sep 18 '15 at 14:32
  • btw.: Your "program" tag names are inconsistent with the "type" tag. What if a nasty user puts in: ``[...]Application[...]``? – Binkan Salaryman Sep 18 '15 at 14:38
  • Just got home and checked, looks like it is icon.extractassociatedicon because it gets called so often. And about the Type, i thought the same thing when i made it, i think i did it because i thought it would make it easier – Jesper Sep 18 '15 at 17:23

2 Answers2

1

To answer the question: You could probably look into caching the icons if that's the issue. Also, in your screenshot you only have 8 icons showing, so you could probably load the rest of them in the background. If you want to get fancier you could load everything asynchronously sort of like Visual Studio's nuget package manager.

Other comments: The xml loading code seems a bit janky - you shouldn't be depending on the order of the attributes. I think Is it possible to deserialize XML into List<T>? is a good start.

Community
  • 1
  • 1
Warty
  • 7,237
  • 1
  • 31
  • 49
  • Yeah, i know i shouldn't depend on the order but i couldn't think of much, i forgot about serializing :-) But i just remade the save/load with XML serialize/deserialize, and it made the code shorter and easier to understand. Now i just need to load the icons in the background :-) So i will be back when i'm done – Jesper Sep 19 '15 at 13:19
1
  1. Redo your XML method. You can quite easily use serialization and deserialization to deal with your loading and saving of the xml.
  2. You should be loading the icons in a background thread. The rest of your application doesnt require the icons to work so you should define a default icon and update the UI with the correct icon once you have it loaded.
  3. You should cache the icons that you have previously loaded. This will avoid you displaying the default icon after the very first run. In a background thread you can scan the executables anyway and update the cache to make sure you have the most recent icon.

On a side note it looks like a cool little application. I wouldnt mind being a tester for you. Update this answer when you're done.

CathalMF
  • 9,705
  • 6
  • 70
  • 106
  • Thanks :-) I'll try tomorrow when i wake up, kinda tired right now :-) I just tried the xml serializing/deserializing, but i can't seem to make it change the root name, of the applicationList(it is of type ObservableCollection), and it is driving me crazy. I'm probably using the attributes wrong. Root name is just but i wan't to change it. I tried to put XmlArray("Applications") above applicationList, but didn't work. I've seen some examples, but i didn't work out for me. But i'll try the other ones tomorrow, then maybe i can get the xml serializing to work – Jesper Sep 18 '15 at 20:41
  • 1
    I re-did save and load, so now it uses XML serialization/deserialization :-) And it looks like it starts up quicker now and not freezing the window. I added a default icon too, so it displays that icon and when all is loaded it will set the real icons. Works great :-) You still want to try it out? – Jesper Sep 19 '15 at 17:56
  • ya sure. post a link here where i can get it. – CathalMF Sep 21 '15 at 08:18