1
\$\begingroup\$

I am creating a video parser in C# WinForms. You select files, they get parsed then a custom control (ViewWideNarrow ) is created showing the video's name, duration and so forth, which is then added to FlowLayoutPanel1.

The user then selects in what order to display said custom controls, titles alphabetically or by Bitrate of the video. My code below works just fine, but it takes a couple of seconds to reorganize around two hundred controls, and I fear on weaker machines it might take even longer, and I wish to optimize the code, or how I handle the custom controls to begin with in respect with modest memory usage. Right now I do not have leaks or high usage.

I decided to use an ID'ing system like so to save memory:

//ID of the control, and ViewWideNarrow is the custom control itself shown in the FlowLayoutPanel
public Dictionary<int, ViewWideNarrow> Lookup_VideoView = new Dictionary<int, ViewWideNarrow>();

//ID of the control and its respective video's bitrate.
public Dictionary<int, int> Lookup_Bitrate = new Dictionary<int, int>();

//ID of the control and its respective video's title.
public Dictionary<int, string> Lookup_Alphabetical = new Dictionary<int, string>(); 

Which I then organize accordingly to use FI-FO kind of system using:

Lookup_Alphabetical = Lookup_Alphabetical.OrderBy(item => item.Value, new ComparerAlphabet()).ToDictionary(item => item.Key, item => item.Value);

Lookup_Bitrate = Lookup_Bitrate.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);

And below is the actual control organization, which is what actually takes a while to complete and is what I suspect needs working on.

private void OrganizeControls()
        {
            if (SortingOption == Sorting.Alphabetical)
            {
                int h = 0;
                foreach (var item in Lookup_Alphabetical)
                {
                    int key = item.Key;
                    string value = item.Value;
                    ViewWideNarrow View = Lookup_VideoView[key];

                    if (FlowLayoutPanel1.Controls.Contains(View))
                    {
            FlowLayoutPanel1.Controls.SetChildIndex(View, h);                        
                        h++;
                    }
                }
            }
    }
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

it takes a couple of seconds to reorganize around two hundred controls

The code that orders the controls has a common omission: it does not temporarily SuspendLayout. So the panel keeps running its layout code for every change, instead of just once after all the changes have been made. In case suspending layout is not enough, you can also consider suspending redraw.

Additionally, the order of the controls seems to rely on the order in which the corresponding key/value pairs occur in a Dictionary. Through a combination of various implementation details, that will often work in a case like this, but Dictionary explicitly anti-promises that:

For purposes of enumeration, each item in the dictionary is treated as a KeyValuePair<TKey,TValue> structure representing a value and its key. The order in which the items are returned is undefined.

You could make a List of keys, ordered by their corresponding values. It does not even need to be a list of key/value pairs, the value is not actually used except for in the sorting step, and the sorting step can look up the value by its key.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ You could make a List of keys, ordered by their corresponding values. Yes that can be very Functionally Oriented (yes Virginia, FO and OO are quite compatible) but a SortedDictionary may serve as well. \$\endgroup\$
    – radarbob
    Commented Jan 6, 2023 at 21:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.