Windows Management Instrumentation. События в WMI. Библиотека классов MyWMI. Особенности работы с большим деревом, страница 17

Имя родительского узла выявляется с помощью метода класса Path. Некоторые пояснения особенностей вызова Invoke можно найти в MSDN. Например, массив объектов (new object[]), который создается по ходу дела, позволяет создать делегатный тип с произвольным числом параметров. Мы используем лишь один параметр: имя вновь созданной папки, а могли бы передать и два и три и т.д.

Итак, мы познакомились со способом запуска произвольного метода (в нашем случае OnDirCreated) в рамках другого потока. Запуск метода с помощью Invoke называется синхронным, так как наш (главный) поток, при этом, ждет завершения вспомогательного потока, то есть временно стоит. Особенность синхронного запуска в том, что нам не надо создавать другой поток—он выбирается из специального множества дежурных потоков (thread pool). Я не знаю, зачем эта технология понадобилась здесь, но она работает.

Запустите и проверьте. С помощью обычного Explorer'а создайте папку в активной директории, и таскайте ее при нажатой клавише Ctrl. Затем удалите некоторые копии, или (нажав F2) переименуйте. Дерево должно послушно отображать все перепитии событий, происходящих в файловой системе. Недостаток — мы способны следить только за тем диском, тем, в котором расположена папка, раскрытая в дереве последней. Если исправите этот недостаток (без помощи новых наблюдателей), то сообщите мне.

Работаем без вызова Invoke

Метод Invoke автоматически создает другой поток и запускает его в синхронном режиме. Это означает, что выполнение текущего потока приостанавливается, пока не отработает вновь созданный. Существует и другой способ запуска любого метода любого класса—асинхронный (при этом работает пара методов BeginInvoke-EndInvoke), но об этом в другой раз и в другом месте.

Прошло некоторе время, пришла новая версия Visual Studio (7.1 и .NET Framework 1.1), были установлены какие-то обновления, установлена и вновь удалена Visual Studio 8.0 (Beta, затем и Beta 2). Все эти операции, как вы знаете не обходятся без обновления системных DLL. Я вновь обратился к к проекту MyWMI с тем, чтобы внести некоторые поправки, и вдруг замечаю, что первоначальный подход к обработке события Created объекта dirWatcher (без привлечения метода Invoke) надежно работает. Вот эта версия.

case WatcherChangeTypes.Created:

  string parent = Path.GetDirectoryName(e.FullPath);      

  if (NodeExists (parent))

   searchNode.Nodes.Add (new TreeNode (Path.GetFileName(e.Name), 10, 11));

  msg = "Directory created: ";

  break;

Оставьте любой из вариантов и не жалейте о времени, затраченном на знакомство с Invoke. Эта техника вам еще пригодится, хотя бы для сдачи Microsoft-экзаменов. А сейчас отметьте, что опять потеряна чувствительность к регистру. Любопытен вариант коррекции этого недостатка, предложенный нашим студентом Тихановским А.С. Вот он.

string parent = Path.GetDirectoryName (e.FullPath);

ManagementObject dir = new ManagementObject ("Win32_Directory.Name='" + e.FullPath+'\'');

string dirName = dir["FileName"].ToString();

if ((showHidden || !((bool)dir["Hidden"])) && NodeExists (parent))

searchNode.Nodes.Add (new TreeNode (dirName, 10, 11));

msg = "Directory created: ";

break;

Здесь, кроме прочего, производится учет флага showHidden, который учитывает, надо-ли показывать папку, если она скрыта.

Список файлов

Прежде, чем задействовать второго наблюдателя fileWatcher, необходимо вычислить список файлов, расположенных в папке, выбранной (selected) в дереве. Это традиционно делается в обработчике события, возбуждаемого в момент выбора папки. В MFC это было уведомление типа =TVN_SELCHANGED, а в .NET — это событие AfterSelect (сравнение показывает насколько реалии .NET ближе к нормальному человеческому языку). Также поступим и мы. Заготовка функции уже есть, осталось вставить в нее код.

private void tree_AfterSelect (object sender, TreeViewEventArgs e)

{

  RefreshList (e.Node);