【问题标题】:WMI searches with c# threading how to work more CPU efficiëntWMI 使用 c# 线程搜索如何提高 CPU 效率
【发布时间】:2013-01-30 23:39:25
【问题描述】:

我有一个程序,它创建一个线程来搜索 WMI(Win32 类)以检查各种系统信息。 现在我为每个搜索创建一个线程,但显然当我使用我的组合框并快速滚动或触发多个线程时,cpu 会出现峰值,即使在关闭表单后,发送的“命令”仍然会发送到 wmi 提供程序,从而导致 cpu飙升了好一阵子……

问题:

在不关闭表单的情况下限制 cpu 使用率/创建的最大线程数以防止 cpu 峰值的最佳方法是什么。 (如果我关闭表单,我可以为 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();
            }
        }
    }

【问题讨论】:

  • 如果你使用 CPU,是的,使用率会飙升!
  • 我知道,我只是想防止 cpu 峰值,当有人滚动组合框时会导致很多新线程 XD 特别是更长的 cpu 峰值 xD
  • 另外,您可能不应该调用每个“选定的更改”!启动计时器,当计时器经过时,检查是否相同的项目(如果不是重新启动计时器),如果相同则搜索....或仅搜索“点击”
  • 不确定,可能 indexchanged 会更好,嗯,它可能会触发 keychanges...

标签: c# multithreading winforms wmi wmi-query


【解决方案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);
}));

【讨论】:

  • 在整个循环中调用调用会导致表单冻结。并在 1 次调用中将整个列表添加到列表视图中,你会怎么做?我试过使用 listView.Items.AddRange(arrList).SubItems.AddRange(arrList2);这是行不通的。所以我回到了foreach..
  • 发现它-_-" 是愚蠢的 listView.Items.AddRange(itemsToAdd.ToArray()); 在不需要时一直尝试创建 listviewitemcollection,只需将列表转换为数组...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多