WMI ищет с помощью потоковой передачи c #, как повысить эффективность ЦП

У меня есть программа, которая создает поток для поиска WMI (классов Win32) для проверки всех видов системной информации. Теперь я создаю поток для каждого поиска, но, очевидно, когда я использую свое поле со списком и быстро прокручиваю или вызываю несколько потоков, процессор будет резко увеличиваться, и даже после закрытия формы отправленные «команды» по-прежнему переходят к провайдеру wmi, вызывая процессор всплеск довольно долго ...

Вопрос:

Каким будет лучший способ ограничить использование процессора / максимальное количество потоков, созданных для предотвращения скачков процессора, не закрывая форму. (Я могу отправить процесс уничтожения для процесса поставщика WMI, если я закрою форму, чтобы остановить его).

Изображение:

введите описание изображения здесь

Код:

namespace Admin_Helper
{
    public partial class frmHardwareInformation : Form
    {
        public frmHardwareInformation()
        {
            InitializeComponent();
        }

        string searchQuery;

        private void cmbItemList_SelectedIndexChanged(object sender, EventArgs e)
        {
            var dctPropertyList = new Dictionary<string, string>(); //Store property name/value
            searchQuery = cmbItemList.SelectedItem.ToString(); //Search term
            new Thread(() => FindWMI(searchQuery, dctPropertyList, lstHwSearchList)).Start(); //Start thread for each search

    }

    private void FindWMI(string s, Dictionary<string, string> dct, ListView listView)
    {
        try
        {
            ManagementObjectSearcher moSearcher = new ManagementObjectSearcher("select * from " + s);

            Invoke(new MethodInvoker(() =>
                {
                    listView.Items.Clear(); //Clear items to prevent endless list
                }));

            foreach (ManagementObject moObject in moSearcher.Get())
            {
                if (moObject != null) //Gives errors if I don't check for null's..
                {
                    foreach (PropertyData propData in moObject.Properties)
                    {
                        if (propData.Value != null && propData.Value.ToString() != "" && propData.Name != null && propData.Name != "") //More prevention of errors..
                            dct[propData.Name] = propData.Value.ToString();

                    }
                }
            }

            foreach (KeyValuePair<string, string> listItem in dct)
            {
                Invoke(new MethodInvoker(() =>
                {
                    listView.Items.Add(listItem.Key).SubItems.Add(listItem.Value);
                    Application.DoEvents();
                }));
            }
        }
        catch (Exception) { } //Mostly catches invalid searches nothing too bad so far
    }
}

}

РЕДАКТИРОВАТЬ: включены изменения кода

* Добавлены процессы убийства при закрытии формы, создание списка и запуск всего обновления в 1x.

private void FindWMI(string s, Dictionary<string, string> dct, ListView listView)
    {

        try
        {
            List<ListViewItem> itemsList = new List<ListViewItem>();

            ManagementObjectSearcher moSearcher = new ManagementObjectSearcher("select * from " + s);
            Invoke(new MethodInvoker(() =>
            {
              listView.Items.Clear();
            }));

            foreach (ManagementObject moObject in moSearcher.Get())
            {
                if (moObject != null)
                {
                    foreach (PropertyData propData in moObject.Properties)
                    {
                        if (propData.Value != null && propData.Value.ToString() != "" && propData.Name != null && propData.Name != "")
                            dct[propData.Name] = propData.Value.ToString();
                    }
                }
            }
            foreach (KeyValuePair<string, string> listItem in dct)
            {
                ListViewItem lstItem = new ListViewItem(listItem.Key);
                lstItem.SubItems.Add(listItem.Value);
                itemsList.Add(lstItem);
            }

            Invoke(new MethodInvoker(() =>
            {
                listView.Items.AddRange(itemsList.ToArray());
            }));
        }
        catch (Exception) { }
    }

    private void frmHardwareInformation_FormClosed(object sender, FormClosedEventArgs e)
    {
        foreach (System.Diagnostics.Process myProc in System.Diagnostics.Process.GetProcesses())
        {
            if (myProc.ProcessName == "WmiPrvSE")
            {
                myProc.Kill();
            }
        }
    }

person Random IT Guy    schedule 30.01.2013    source источник
comment
если вы используете ЦП, да, загрузка вырастет!   -  person Mitch Wheat    schedule 31.01.2013
comment
Я знаю это, я просто хочу предотвратить скачки процессора, когда кто-то будет прокручивать поле со списком, вызывая много новых потоков XD Особенно длинные скачки процессора xD   -  person Random IT Guy    schedule 31.01.2013
comment
Кроме того, вы, вероятно, не должны вызывать каждое «выбранное изменение»! Запустите таймер, когда таймер истечет, проверьте, есть ли тот же элемент (если не перезапустите таймер), если такой же, то ищите .... ИЛИ ищите только по 'щелчку'   -  person Mitch Wheat    schedule 31.01.2013
comment
Не был уверен в этом, наверное, indexchanged было бы лучше, хм, он может сработать только при смене клавиш ...   -  person Random IT Guy    schedule 31.01.2013


Ответы (1)


Для повышения производительности вам определенно следует избегать вызова Control.Invoke () в ваших циклах. Вместо этого вы можете обернуть весь цикл в Control.Invoke () или, что еще лучше, создать список элементов для отображения, а затем обновить свой элемент управления за один вызов Control.Invoke (). Это позволит вам избежать снижения производительности, если вы реализовали дополнительную фильтрацию элементов, выполняя их в потоке, отличном от GUI.

Кроме того, вам не понадобится вызов Application.DoEvents ().

Вот пример того, что я имею в виду, создавая список элементов и добавляя их в элемент управления позже:

var itemsToAdd = new List<ListViewItem>();
foreach (KeyValuePair<string, string> listItem in dct)
{
    ListViewItem item = new ListViewItem(listItem.Key);
    item.SubItems.Add(listItem.Value);
    itemsToAdd.Add(item);
}

Invoke(new MethodInvoker(() =>
{
    listview.Items.AddRange(itemsToAdd);
}));
person itsme86    schedule 30.01.2013
comment
Размещение invoke по всему циклу приводит к зависанию формы. И чтобы добавить весь список в список за один вызов, как бы вы это сделали? Я пробовал использовать listView.Items.AddRange (arrList) .SubItems.AddRange (arrList2); что не сработает. Итак, я вернулся к foreach .. - person Random IT Guy; 31.01.2013
comment
Нашел -_- был тупым listView.Items.AddRange (itemsToAdd.ToArray ()); Продолжал пытаться создать listviewitemcollection, пока он не нужен, просто нужно было преобразовать список в массив ... - person Random IT Guy; 31.01.2013