2012-05-10 4 views
0

То, что я пытаюсь выполнить в своей программе, - это знать, работают ли определенные процессы (мне нужно знать обо всех запущенных экземплярах). Я хочу держать их в combobox, хранить как объект, поэтому я могу отбросить их позже. Я думал, что это будет легко, но, как выяснилось, это вызвало у меня головную боль: P Я не уверен, что так оно и должно быть сделано, но оно работает. Тем не менее, мне плохо в этом решении. Я не знаю хороших шаблонов программирования для этого, поэтому я прошу вас, коллеги-кодеры, помочь мне.Операции процесса (мониторинг)

Первое, что пришло мне в голову, - использовать таймер для проверки процессов и добавить их, а также использовать событие «Выход», чтобы удалить их из моего списка. Так вот мой код на Tick событие таймера:

private void timer_ProcessCheck_Tick(object sender, EventArgs e) 
    { 
     Process[] tmpArray = Wow_getCurrentlyRunning(); // this returns Process[] 
     if (comboBox_processes.Items.Count == 0) 
     { 
      if (tmpArray.Count() > 0) 
       for (int Index = 0; Index < tmpArray.Count(); Index++) 
        Add(tmpArray[Index]); // adding to combobox 
     } 
     else 
     { 
      if (tmpArray.Count() > comboBox_processes.Items.Count) 
      { 
       List<Process> result; 
     /*Diff compares the two array, and returns to result variable.*/ 
       if (Diff(tmpArray, comboBox_processes, out result))     
        foreach(Process proc in result) 
         Add(proc); // adding to combobox 
      } 
     } 
    } 

И мой метод Diff выглядит так, что поставит разницу дифф переменной.

public bool Wow_differsFrom(Process[] current, ComboBox local, out List<Process> diff) 
    { 
     List<int> diffIndex = new List<int>(); 

     foreach (Process proc in current) 
      diffIndex.Add(proc.Id); 

     for (byte Índex = 0; Índex < current.Count(); Índex++) 
     { 
      for (byte Index = 0; Index < local.Items.Count; Index++) 
      { 
       if (current[Índex].Id == (local.Items[Index] as Process).Id) 
       { 
        diffIndex.Remove(current[Índex].Id); 
        break; 
       } 
      } 
     } 

     diff = new List<Process>(); 

     for (int x = 0; x < current.Count(); x++) 
      for (int i = 0; i < diffIndex.Count; i++) 
       if (current[x].Id == diffIndex[i]) 
        diff.Add(current[x]); 

     if (diff.Count == 0) 
      return false; 
     return true; 
    } 

Вот обработчик события возбужденном дозвонились на платформе завершения процесса

private void Wow_exitedEvent(object o, EventArgs e) 
    { 
     RemoveCBItem(comboBox_processes, (o as Process).Id); // this will remove the process from combobox, also threadsafe. 
    } 

Мои вопросы:

  1. Как бы вы это сделали? Подхожу ли я к этому правилу? У меня такое чувство, я не знаю.

  2. Есть ли какие-либо события для подачи заявки? Как и один для выхода . Может быть, глубоко в Win32 API?

ответ

1

В целом идея правильная, я думаю - если вам нужно обновлять список активных процессов каждый раз. Поэтому обновление списка с использованием таймера в порядке. Я не знаю Win32 API очень хорошо, но я думаю, что это будет проблема безопасности, если кто-нибудь может подписаться на process_run и process_retminate винные события, так что это вряд ли возможно.

Но вам действительно нужно постоянно обновлять его? Может быть, вам будет достаточно, чтобы прочитать список процессов только при расширении combobox? Когда пользователь в следующий раз расширит его, вы снова заново создадите элементы. Я думаю, что такой подход вызовет меньше проблем.

Как Ф.О. вашей реализации, я думаю, что это не самый effifient и элегантна:

  1. Сохранение всего объекта процесса в элементе не поле со списком хорошо, как для меня. Лучше создайте свой класс, который будет хранить только те свойства, которые вам нужны (Идентификатор процесса, Имя процесса)
  2. using current.Count() в цикле крайне неэффективен - это метод расширения, который всегда выполняет итерацию на IEnumerable при вызове. Так что ваши

    для (байт INDEX = 0; INDEX < current.Count(); INDEX ++)

    приводит к O (N * N) сложности. К счастью, количество процессов будет не слишком большим, чтобы сильно повлиять на ваше приложение, но вы должны знать этот факт и не привыкать использовать этот метод в цикле. используйте current.Length вместо этого, поскольку это массив.

  3. Синхронизация вашей коллекции слишком сложная и странная. Почему бы не сделать метод, который получает коллекцию для изменения и сбора для init, и делает первую коллекцию равной второй, используя операции добавления-удаления? У вас будут обе коллекции, отсортированные по некоторому свойству (например, имя процесса), это можно сделать очень просто и эффективно - используя binary search. В WPF вы можете использовать ObservableCollection в качестве источника данных для наиболее эффективного использования этого подхода. В WinForms вы, вероятно, также можете использовать коллекции с уведомлением об изменениях, но я их не использовал.

Вы можете сделать это еще проще:

//Somewhere in Form_Load 
combobox.DisplayMember = "Name";//name of the property in your MyProcessInfo class 
combobox.ValueMember = "Id";//name of the property in your MyProcessInfo class 

//In your timer.Tick handler 
combobox.DataSource = Wow_getCurrentlyRunning().Select(p=>new MyProcessInfo(p.Id, p.Name)).ToList(); 

Но этот подход будет всегда переинициализации все пункты, если выпадающий и некоторые мигания возможно.

+0

У меня возникло чувство об этом, что вы сказали о Win API = ( У меня есть эта странная привычка хранить мои объекты в собственности владельца элемента управления, когда я могу, разве это не так эффективно? Или это другое Кстати, по методу Count() - да, спасибо за напоминание :) Я полностью забыл об этом. Что касается предложения привязки данных, я попытался с этим при первом подходе, и я решил не использовать его из-за мигания. Что вы подразумеваете под кодом coll.synch? Мой метод Diff? –

+0

На самом деле, да, метод синхронизации - это ваш метод Diff. Но он может быть реализован гораздо более ясным и простым. Извините, но у меня нет времени, чтобы написать его сейчас = (. Общая идея: сортировать обе коллекции, искать каждый элемент первой коллекции во втором. Если не найдено - удалить элемент из первой коллекции. 1: если не найдено - добавьте его. –

+0

И что с моим подходом для загрузки данных в combobox не по таймеру.Только, но на combobox_Expand? Не уместно? –

Смежные вопросы