1

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();
            }
        }
    }
4

1 に答える 1

2

パフォーマンスを改善するには、ループ内で 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);
}));
于 2013-01-30T23:58:32.547 に答える