Оптимизация кода программы
От: nettro  
Дата: 02.04.12 12:55
Оценка:
Доброго времени суток!
Проблема в следующем: написал программу на c#, которая опрашивает сеть на наличие пингующихся компьютеров в сети, и если компьютер пингуется, ему посылаются wmi запросы по сбору информации о его конфигурации (пока собирается инфа о процессоре, памяти, хардах и видеоадаптере) и всё это дело выводиться в richTextBox (планируется записывать всё это дело в базу, но пока по этому поводу не думал). Так вот, если в сети доступны компов 30, то данная операция опроса выполняется минут 5 и при выполнении форма программы просто зависает и с ней ничего нельзя сделать...
Помогите пожалуйста решить эту проблему, что бы уменьшить время выполнения программы и главное что бы программа не подвисала?

p.s. Если кто то откликнется на тему и поможет на конкретном примере привязать BackgroundWorker и ProgressBar к проге, а то сколько не пытаюсь по статьям с msdn, как то пока не получается... По необходимости могу прислать проект с кодом.

Спасибо!
visual studio c#
Re: Оптимизация кода программы
От: Glas  
Дата: 02.04.12 13:27
Оценка:
Здравствуйте, nettro, Вы писали:

N>Доброго времени суток!

N>Проблема в следующем: написал программу на c#, которая опрашивает сеть на наличие пингующихся компьютеров в сети, и если компьютер пингуется, ему посылаются wmi запросы по сбору информации о его конфигурации (пока собирается инфа о процессоре, памяти, хардах и видеоадаптере) и всё это дело выводиться в richTextBox (планируется записывать всё это дело в базу, но пока по этому поводу не думал). Так вот, если в сети доступны компов 30, то данная операция опроса выполняется минут 5 и при выполнении форма программы просто зависает и с ней ничего нельзя сделать...
N>Помогите пожалуйста решить эту проблему, что бы уменьшить время выполнения программы и главное что бы программа не подвисала?

N>p.s. Если кто то откликнется на тему и поможет на конкретном примере привязать BackgroundWorker и ProgressBar к проге, а то сколько не пытаюсь по статьям с msdn, как то пока не получается... По необходимости могу прислать проект с кодом.


N>Спасибо!


Использовать многопоточность пробовали? Сделайте обработку wmi запросов в отдельных потоках и по мере их завершения заполняйте форму. Этим освободите поток формы и он будет доступна.
Re[2]: Оптимизация кода программы
От: nettro  
Дата: 02.04.12 13:45
Оценка:
Здравствуйте, Glas, Вы писали:

G>Здравствуйте, nettro, Вы писали:


N>>Доброго времени суток!

N>>Проблема в следующем: написал программу на c#, которая опрашивает сеть на наличие пингующихся компьютеров в сети, и если компьютер пингуется, ему посылаются wmi запросы по сбору информации о его конфигурации (пока собирается инфа о процессоре, памяти, хардах и видеоадаптере) и всё это дело выводиться в richTextBox (планируется записывать всё это дело в базу, но пока по этому поводу не думал). Так вот, если в сети доступны компов 30, то данная операция опроса выполняется минут 5 и при выполнении форма программы просто зависает и с ней ничего нельзя сделать...
N>>Помогите пожалуйста решить эту проблему, что бы уменьшить время выполнения программы и главное что бы программа не подвисала?

N>>p.s. Если кто то откликнется на тему и поможет на конкретном примере привязать BackgroundWorker и ProgressBar к проге, а то сколько не пытаюсь по статьям с msdn, как то пока не получается... По необходимости могу прислать проект с кодом.


N>>Спасибо!


G>Использовать многопоточность пробовали? Сделайте обработку wmi запросов в отдельных потоках и по мере их завершения заполняйте форму. Этим освободите поток формы и он будет доступна.


Ну я пытаюсь привязать BackgroundWorker к проге, как написано в mdsn этот класс как раз выполняет операцию в отдельном потоке. Но пока всё безуспешно...
Re[3]: Оптимизация кода программы
От: Glas  
Дата: 02.04.12 13:58
Оценка:
Здравствуйте, nettro, Вы писали:

N>Ну я пытаюсь привязать BackgroundWorker к проге, как написано в mdsn этот класс как раз выполняет операцию в отдельном потоке. Но пока всё безуспешно...


Ваш код для работы с BackgroundWorker показать можете? Ну или если с ним разобраться не можете, можно использовать класс Thread.
Re: Оптимизация кода программы
От: motormanyak Земля  
Дата: 02.04.12 14:41
Оценка:
Здравствуйте, nettro, Вы писали:

N>Доброго времени суток!

N>Проблема в следующем: написал программу на c#, которая опрашивает сеть на наличие пингующихся компьютеров в сети, и если компьютер пингуется, ему посылаются wmi запросы по сбору информации о его конфигурации (пока собирается инфа о процессоре, памяти, хардах и видеоадаптере) и всё это дело выводиться в richTextBox (планируется записывать всё это дело в базу, но пока по этому поводу не думал). Так вот, если в сети доступны компов 30, то данная операция опроса выполняется минут 5 и при выполнении форма программы просто зависает и с ней ничего нельзя сделать...
N>Помогите пожалуйста решить эту проблему, что бы уменьшить время выполнения программы и главное что бы программа не подвисала?

N>p.s. Если кто то откликнется на тему и поможет на конкретном примере привязать BackgroundWorker и ProgressBar к проге, а то сколько не пытаюсь по статьям с msdn, как то пока не получается... По необходимости могу прислать проект с кодом.


N>Спасибо!


Здесь BackgroundWorker не совсем подходит. В него можно вынести цикл опроса, что разлочит главное окно, но не ускорит процесс выполнения. Чтобы ускорить процесс выполнения, каждую итерацию следует вынести в отдельный поток (класс Thread).

Код в помощь

        public TResult[] Execute<T, TResult>(Func<T, TResult> func, ICollection<T> collection)
        {
            IAsyncResult[] handles = new IAsyncResult[collection.Count()];
            int i = 0;
            foreach (T element in collection)
                handles[i++] = func.BeginInvoke(element, null, null);

            i = 0;
            TResult[] result = new TResult[collection.Count()];
            foreach (IAsyncResult handle in handles)
                result[i++] = func.EndInvoke(handle);
            return result;
            //dispath an event here
        }


Func<T, TResult> func — функция, которая собирает инфу с компа
ICollection<T> collection — коллекция доступных компов

вызов:

String[] comps[] = new String[] {......};
Func<String, String> func = new Func<String, String>( host => Collect_Info_And_Return_String(host) );
String[] results = null;
new Thread( _ => results = Execute<String, String>(func, comps) ).Start();


results лучше прибиндить к richTextBox. так не надо будет следить за окончанием выполнения потока. или можно добавить событие (см. выше) и по событию отображать результат
еще следует помнить, что элементы коллекции collection будут обрабатываться функцией func в произвольном порядке
In God We Trust
Re: Оптимизация кода программы
От: Fortnum  
Дата: 02.04.12 15:37
Оценка:
Здравствуйте, nettro, Вы писали:

N>p.s. Если кто то откликнется на тему и поможет на конкретном примере привязать BackgroundWorker и ProgressBar к проге, а то сколько не пытаюсь по статьям с msdn, как то пока не получается... По необходимости могу прислать проект с кодом.


WPF или WinForms?
Re[2]: Оптимизация кода программы
От: Fortnum  
Дата: 02.04.12 15:43
Оценка:
Здравствуйте, motormanyak, Вы писали:

N>>p.s. Если кто то откликнется на тему и поможет на конкретном примере привязать BackgroundWorker и ProgressBar к проге, а то сколько не пытаюсь по статьям с msdn, как то пока не получается... По необходимости могу прислать проект с кодом.

M>Здесь BackgroundWorker не совсем подходит. В него можно вынести цикл опроса, что разлочит главное окно, но не ускорит процесс выполнения. Чтобы ускорить процесс выполнения, каждую итерацию следует вынести в отдельный поток (класс Thread).

А где же обновление ProgressBar'а?
Re[3]: Оптимизация кода программы
От: motormanyak Земля  
Дата: 02.04.12 16:21
Оценка: 1 (1)
Здравствуйте, Fortnum, Вы писали:

F>Здравствуйте, motormanyak, Вы писали:


N>>>p.s. Если кто то откликнется на тему и поможет на конкретном примере привязать BackgroundWorker и ProgressBar к проге, а то сколько не пытаюсь по статьям с msdn, как то пока не получается... По необходимости могу прислать проект с кодом.

M>>Здесь BackgroundWorker не совсем подходит. В него можно вынести цикл опроса, что разлочит главное окно, но не ускорит процесс выполнения. Чтобы ускорить процесс выполнения, каждую итерацию следует вынести в отдельный поток (класс Thread).

F>А где же обновление ProgressBar'а?


да запросто

        public TResult[] Execute<T, TResult>(Func<T, TResult> func, ICollection<T> collection)
        {
            IAsyncResult[] handles = new IAsyncResult[collection.Count()];
            int i = 0;
            foreach (T element in collection)
                handles[i++] = func.BeginInvoke(element, null, null);

            i = 0;
            int percent = 0;
            TResult[] result = new TResult[collection.Count()];
            foreach (IAsyncResult handle in handles)
            {
                result[i++] = func.EndInvoke(handle);
                percent = Math.Round(i / collection.Count * 100);
                progressBar.Invoke((Action)(delegate {  p.Value = percent; }));
            }
            return result;
            //dispatсh an event here
        }


но по-хорошему, все это надо вынести в отдельный класс, который не будет знать о progressBar. а на месте progressBar.Invoke диспатчить событие (возможно даже тогоже типа, что и BackgroundWorker диспатчит).

п.с. последние изменения не проверял, но думаю должно сработать
In God We Trust
Re[4]: Оптимизация кода программы
От: Fortnum  
Дата: 02.04.12 16:36
Оценка:
Здравствуйте, motormanyak, Вы писали:

F>>А где же обновление ProgressBar'а?

M>да запросто
M>но по-хорошему, все это надо вынести в отдельный класс, который не будет знать о progressBar. а на месте progressBar.Invoke диспатчить событие (возможно даже тогоже типа, что и BackgroundWorker диспатчит).
M>п.с. последние изменения не проверял, но думаю должно сработать

А почему бы тогда не воспользоваться BackgroundWorker'ом, который уже как бы представляет собой этот отдельный класс? По-хорошему тут не в один поток это все надо засовывать, а использовать AsyncCallback. И ни в коем случае не вызывать EndInvoke() раньше времени, тем более в цикле. Иначе первый же отсутствующий в сетке хост из списка застопорит этот отдельный поток в своих таймаутах и никакой радости вы не получите. Отдельный класс, конечно, напрашивается. Обновление ProgressBar'а выполнять в AsyncCallback'ах.

Топикстартеру пример работы ProgressBar vs. BackgroundWorker на WPF.
Re[4]: Оптимизация кода программы
От: nettro  
Дата: 02.04.12 16:55
Оценка:
Здравствуйте, Glas, Вы писали:

G>Здравствуйте, nettro, Вы писали:


N>>Ну я пытаюсь привязать BackgroundWorker к проге, как написано в mdsn этот класс как раз выполняет операцию в отдельном потоке. Но пока всё безуспешно...


G>Ваш код для работы с BackgroundWorker показать можете? Ну или если с ним разобраться не можете, можно использовать класс Thread.


http://ifolder.ru/29673465
вот сюда залил свой проект, делал в vs2010

Здравствуйте, Fortnum, Вы писали:

F>Здравствуйте, nettro, Вы писали:


N>>p.s. Если кто то откликнется на тему и поможет на конкретном примере привязать BackgroundWorker и ProgressBar к проге, а то сколько не пытаюсь по статьям с msdn, как то пока не получается... По необходимости могу прислать проект с кодом.


F>WPF или WinForms?


Если я правильно понял описание что такое WPF на вики, то моя прога это WinForms
Re[5]: Оптимизация кода программы
От: nettro  
Дата: 02.04.12 17:01
Оценка:
Здравствуйте, nettro, Вы писали:

N>Здравствуйте, Glas, Вы писали:


G>>Здравствуйте, nettro, Вы писали:


N>>>Ну я пытаюсь привязать BackgroundWorker к проге, как написано в mdsn этот класс как раз выполняет операцию в отдельном потоке. Но пока всё безуспешно...


G>>Ваш код для работы с BackgroundWorker показать можете? Ну или если с ним разобраться не можете, можно использовать класс Thread.


N>http://ifolder.ru/29673465

N>вот сюда залил свой проект, делал в vs2010

ой, только по этому пути, на ifolder лежит проект без работы с BackgroundWorker... т.к. пытаюсь на работе его прикрутить, ничего не вышло, и в конце дня забыл отбекапить его...
Re[5]: Оптимизация кода программы
От: igor-booch Россия  
Дата: 02.04.12 18:56
Оценка:
F>А почему бы тогда не воспользоваться BackgroundWorker'ом,

BackgroundWorker'ом можно корректно (без Abort) завершить поток при необходимости. Автору это может и не нужно.
http://rsdn.ru/Info/rules.xml
Re[6]: Оптимизация кода программы
От: Fortnum  
Дата: 02.04.12 19:39
Оценка:
Здравствуйте, igor-booch, Вы писали:

F>>А почему бы тогда не воспользоваться BackgroundWorker'ом,

IB>BackgroundWorker'ом можно корректно (без Abort) завершить поток при необходимости. Автору это может и не нужно.

Не понял, каким образом этот факт влияет на выбор между использованием BackgroundWorker'а и запуском отдельного Thread'а? Прерывать Thread Abort'ом вообще крайне не рекомендуется. К тому же, Abort'ом при необходимости можно и BackgroundWorker завершить:

static void Main(string[] args)
{
    var backgroundWorker = new BackgroundWorker()
    {
        WorkerReportsProgress = true
    };

    backgroundWorker.DoWork += (o, e) =>
    {
        backgroundWorker.ReportProgress(0, Thread.CurrentThread);

        while (true)
        {
            Console.Write('.');
        }
    };

    backgroundWorker.ProgressChanged += (o, e) =>
    {
        var thread = (Thread)e.UserState;

        Thread.Sleep(10);

        thread.Abort();
    };

    backgroundWorker.RunWorkerAsync();
            
    Console.ReadKey();
}
Re[6]: Оптимизация кода программы
От: nettro  
Дата: 03.04.12 05:15
Оценка:
Извиняюсь за наглость, но никто не смотрел код с проектом? Если у кого то есть возможность объяснить или показать как на его примере внедрить BackgroundWorker, буду Вам очень благодарен!! а то что то после 2х суток чтения разных источников, в голове появились не знания, а путаница какая то...
Re[7]: Оптимизация кода программы
От: Fortnum  
Дата: 03.04.12 06:25
Оценка: 23 (2) +1
Здравствуйте, nettro, Вы писали:

N>Извиняюсь за наглость, но никто не смотрел код с проектом? Если у кого то есть возможность объяснить или показать как на его примере внедрить BackgroundWorker, буду Вам очень благодарен!! а то что то после 2х суток чтения разных источников, в голове появились не знания, а путаница какая то...


Смотрю. Во-первых, у меня на компьютере адреса не только IPv4, поэтому вот эту строчку получения IP-адреса:

System.Net.IPAddress ipLocalHost = System.Net.Dns.GetHostEntry(nameLocalHost).AddressList[0];


надо переписать, например, вот так:

var ipLocalHost = Dns.GetHostEntry(nameLocalHost).AddressList.Where(ipAddr => ipAddr.AddressFamily == AddressFamily.InterNetwork).FirstOrDefault();

if (ipLocalHost == null)
    MessageBox.Show("Не найдено ни одного IPv4-адреса.");


Во-вторых, форма подвисает не из-за самого процесса пропинговки, т.к. вызываете пропинговку вы асинхронным способом. Пингуете вы по IP-адресу, а не по имени хоста, поэтому задержек от DNS-сервера не должно быть, значит вызов Ping.SendAsync можно оставить как есть, в UI-потоке. Проблема в обработчике события Ping.PingCompleted, который вызывается не в рабочем потоке — потоке из пула потоков, в котором, собственно, производился пинг, а вызывается в том же UI-потоке, из которого был вызван метод Ping.SendAsync. А это значит, что все то, что происходит в обработчике Ping.PingCompleted тормозит UI. А происходит у вас там вызов метода WmiInfo(e.Reply.Address.ToString()). Тупо прерывая кнопкой Pause во время работы вашего приложения под отладкой, когда форма висит, видно, что задержки возникают на вызове ManagementScope.Connect().

Короче, вызов WmiInfo надо выносить в рабочий поток. Для этого не обязательно использовать BackgroundWorker. Можно воспользоваться методом ThreadPool.QueueUserWorkItem:

ThreadPool.QueueUserWorkItem(state => WmiInfo(e.Reply.Address.ToString()));


Но надо иметь в виду, что теперь метод WmiInfo будет исполняться не-UI-потоком. Более того, этот метод будет исполняться многими потоками параллельно, то есть одновременно. В первую, наверное, очередь это приведет к ошибке "Cross-thread operation not valid: Control 'richTextBox1' accessed from a thread other than the thread it was created on", которая возникнет на первом же вашем richTextBox1.Text += "..." в WmiInfo. Идея в том, что из не-UI-потока нельзя обращаться к свойствам и методам UI-контролов. К ним можно обращаться только из того потока, в котором эти контролы были созданы. Чтобы понять, почему существует такое ограничение, достаточно представить себе, что если бы такое обращение к UI-контролам из разных потоков было бы возможно, то в вашем richTextBox1 вы получили бы просто мусор, т.к. каждый параллельно выполняющийся WmiInfo валил бы туда свои строчки, независимо от других. А т.к. в UI каждое действие над UI-контролом может вызывать различную реакцию, и последовательность этой реакции критически важна, то и существует такое ограничение на обращение к UI-контролам только из UI-потока.

Нет, вы конечно же можете каждый ваш richTextBox1.Text += "..." в WmiInfo обернуть в посылку задачи по выводу этой строки UI-потоку. Например, так:

BeginInvoke(((Action)(() => richTextBox1.Text += "...")));


Но это не спасет вас от рассинхронизации вывода в этот richTextBox1 между различными экземплярами параллельно исполняющихся WmiInfo. Поэтому, в итоге, хоть и без Exception'ов, но в richTextBox1 вы получите все тот же мусор. Как вариант, использовать для форматирования текста в WmiInfo экземпляр StringBuilder, а вывод в richTextBox1 делать в конце WmiInfo. Надо только учесть еще рассинхронизацию вызова richTextBox1.Text += "...", который будет идти непосредственно перед вызовом ThreadPool.QueueUserWorkItem(state => WmiInfo(...)).

BackgroundWorker'ом пока не заморачивайтесь. Вам важнее понять, что происходит и почему. Тот же ProgressBar легко делается и без BackgroundWorker'а. Этот BackgroundWorker — это лишь один из способов, и в большинстве случаев не самый лучший.
Re[5]: Оптимизация кода программы
От: motormanyak Земля  
Дата: 03.04.12 07:24
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>А почему бы тогда не воспользоваться BackgroundWorker'ом, который уже как бы представляет собой этот отдельный класс?

BackgroundWorker здесь не подходит, как я раньше писал, из-за того, что сбор информации лучше проводить в разных потоках одновременно, а не в одном по очереди.

F>По-хорошему тут не в один поток это все надо засовывать, а использовать AsyncCallback.

Тут и так не один поток используется. Вызывать эту функцию надо в еще одном отдельном потоке (см. пост выше)

F>И ни в коем случае не вызывать EndInvoke() раньше времени, тем более в цикле. Иначе первый же отсутствующий в сетке хост из списка застопорит этот отдельный поток в своих таймаутах и никакой радости вы не получите.

EndInvoke в цикле ничего плохого не сделает: если поток завершился, то EndInvoke вернет управление мгновенно. А чтоб отдельный поток не завис навсегда, нужно это в функции предусмотреть.

F>Обновление ProgressBar'а выполнять в AsyncCallback'ах.

Согласен, поспешил когда писал
In God We Trust
Re[6]: Оптимизация кода программы
От: Fortnum  
Дата: 03.04.12 07:42
Оценка:
Здравствуйте, motormanyak, Вы писали:

F>>А почему бы тогда не воспользоваться BackgroundWorker'ом, который уже как бы представляет собой этот отдельный класс?

M>BackgroundWorker здесь не подходит, как я раньше писал, из-за того, что сбор информации лучше проводить в разных потоках одновременно, а не в одном по очереди.

Точно, ждать ответа на пинг в отдельном потоке бессмысленно — не подходит.

F>>По-хорошему тут не в один поток это все надо засовывать, а использовать AsyncCallback.

M>Тут и так не один поток используется. Вызывать эту функцию надо в еще одном отдельном потоке (см. пост выше)

А для этого как раз сгодится.

F>>И ни в коем случае не вызывать EndInvoke() раньше времени, тем более в цикле. Иначе первый же отсутствующий в сетке хост из списка застопорит этот отдельный поток в своих таймаутах и никакой радости вы не получите.

M>EndInvoke в цикле ничего плохого не сделает: если поток завершился, то EndInvoke вернет управление мгновенно. А чтоб отдельный поток не завис навсегда, нужно это в функции предусмотреть.

А как предусмотреть? Не вызывать EndInvoke, а ждать Callback
Re[8]: Оптимизация кода программы
От: nettro  
Дата: 03.04.12 07:51
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>Здравствуйте, nettro, Вы писали:


N>>Извиняюсь за наглость, но никто не смотрел код с проектом? Если у кого то есть возможность объяснить или показать как на его примере внедрить BackgroundWorker, буду Вам очень благодарен!! а то что то после 2х суток чтения разных источников, в голове появились не знания, а путаница какая то...


F>Смотрю. Во-первых, у меня на компьютере адреса не только IPv4, поэтому вот эту строчку получения IP-адреса:


F>
System.Net.IPAddress ipLocalHost = System.Net.Dns.GetHostEntry(nameLocalHost).AddressList[0];


F>надо переписать, например, вот так:


F>
var ipLocalHost = Dns.GetHostEntry(nameLocalHost).AddressList.Where(ipAddr => ipAddr.AddressFamily == AddressFamily.InterNetwork).FirstOrDefault();

if (ipLocalHost == null)
    MessageBox.Show("Не найдено ни одного IPv4-адреса.");


F>Во-вторых, форма подвисает не из-за самого процесса пропинговки, т.к. вызываете пропинговку вы асинхронным способом. Пингуете вы по IP-адресу, а не по имени хоста, поэтому задержек от DNS-сервера не должно быть, значит вызов Ping.SendAsync можно оставить как есть, в UI-потоке. Проблема в обработчике события Ping.PingCompleted, который вызывается не в рабочем потоке — потоке из пула потоков, в котором, собственно, производился пинг, а вызывается в том же UI-потоке, из которого был вызван метод Ping.SendAsync. А это значит, что все то, что происходит в обработчике Ping.PingCompleted тормозит UI. А происходит у вас там вызов метода WmiInfo(e.Reply.Address.ToString()). Тупо прерывая кнопкой Pause во время работы вашего приложения под отладкой, когда форма висит, видно, что задержки возникают на вызове ManagementScope.Connect().


F>Короче, вызов WmiInfo надо выносить в рабочий поток. Для этого не обязательно использовать BackgroundWorker. Можно воспользоваться методом ThreadPool.QueueUserWorkItem:


F>
ThreadPool.QueueUserWorkItem(state => WmiInfo(e.Reply.Address.ToString()));


F>Но надо иметь в виду, что теперь метод WmiInfo будет исполняться не-UI-потоком. Более того, этот метод будет исполняться многими потоками параллельно, то есть одновременно. В первую, наверное, очередь это приведет к ошибке "Cross-thread operation not valid: Control 'richTextBox1' accessed from a thread other than the thread it was created on", которая возникнет на первом же вашем richTextBox1.Text += "..." в WmiInfo. Идея в том, что из не-UI-потока нельзя обращаться к свойствам и методам UI-контролов. К ним можно обращаться только из того потока, в котором эти контролы были созданы. Чтобы понять, почему существует такое ограничение, достаточно представить себе, что если бы такое обращение к UI-контролам из разных потоков было бы возможно, то в вашем richTextBox1 вы получили бы просто мусор, т.к. каждый параллельно выполняющийся WmiInfo валил бы туда свои строчки, независимо от других. А т.к. в UI каждое действие над UI-контролом может вызывать различную реакцию, и последовательность этой реакции критически важна, то и существует такое ограничение на обращение к UI-контролам только из UI-потока.


F>Нет, вы конечно же можете каждый ваш richTextBox1.Text += "..." в WmiInfo обернуть в посылку задачи по выводу этой строки UI-потоку. Например, так:


F>
BeginInvoke(((Action)(() => richTextBox1.Text += "...")));


F>Но это не спасет вас от рассинхронизации вывода в этот richTextBox1 между различными экземплярами параллельно исполняющихся WmiInfo. Поэтому, в итоге, хоть и без Exception'ов, но в richTextBox1 вы получите все тот же мусор. Как вариант, использовать для форматирования текста в WmiInfo экземпляр StringBuilder, а вывод в richTextBox1 делать в конце WmiInfo. Надо только учесть еще рассинхронизацию вызова richTextBox1.Text += "...", который будет идти непосредственно перед вызовом ThreadPool.QueueUserWorkItem(state => WmiInfo(...)).


F>BackgroundWorker'ом пока не заморачивайтесь. Вам важнее понять, что происходит и почему. Тот же ProgressBar легко делается и без BackgroundWorker'а. Этот BackgroundWorker — это лишь один из способов, и в большинстве случаев не самый лучший.


Во-первых огромное Вам спасибо за ответ!!! Вы единственный человек с кучи форумов, который хоть посмотрел мой горе проект и откомментировал его по факту, а не фразами "почитайте msdn", который я читал, но в силу своей неопытности программирования, мало что полезного вынес оттуда...

По поводу отсутствия в программе IPv6, я пока ограничился IPv4 ибо он используется в 98% случаев, да и я не рассчитываю что моя программа будет претендовать на какие то коммерческие решения или что то подобное, пишу её для института и в помощь системным администраторам, т.к. сам сталкивался в сборе подобной информации, а т.к. пиратсвом заниматься не хочется, смотрел в сторону бесплатного софта, выбор которого сводился к 1-2 программам подобного типа со своими минусами, а в больших конторах, другие деньги, и там нет смысла искать бесплатные программы для инвентаризации железа и софта. Но за комментарий и пример кода спасибо, в дальнейшем, если получиться заставить работать программу с потоками, постараюсь обязательно учесть Ваше замечание.

По поводу функции WmiInfo, как Вы могли заметить, в коде описания кнопочки запуска, есть закомментированная строчка вызова WmiINfo:
foreach (string ipRemoteHost in ipRemoteHostList)
{
    asinhroPing(ipRemoteHost);
    //WmiInfo();
}

с самого начала WmiInfo запускалось там, перенос её вызова в funkPingCompleted было тестом, для оценки изменится ли время выполнения или нет.

По поводу
F>Короче, вызов WmiInfo надо выносить в рабочий поток. Для этого не обязательно использовать BackgroundWorker. Можно воспользоваться методом ThreadPool.QueueUserWorkItem:
ThreadPool.QueueUserWorkItem(state => WmiInfo(e.Reply.Address.ToString()));


не могли бы Вы подсказать, как правильнее поступить с функцией WmiInfo, вынести приведённый Вами кусочек кода это в отдельную функцию или вставить этот код в обработку кнопки запуска программы, или же оставить её в этом где она находится на данных момент?

F>Как вариант, использовать для форматирования текста в WmiInfo экземпляр StringBuilder, а вывод в richTextBox1 делать в конце WmiInfo. Надо только учесть еще рассинхронизацию вызова richTextBox1.Text += "...", который будет идти непосредственно перед вызовом ThreadPool.QueueUserWorkItem(state => WmiInfo(...)).


Что касается richTextBox1, я пока не знаю временно это или оставить его, но в дальнейшем я планирую как то всё эти данные полученные с компьютеров записывать в базу и в следствии этого хотелось бы узнать узнать мнение с высоты Вашего опыта, как это лучше организовать?
Большое спасибо!
Re[9]: Оптимизация кода программы
От: Fortnum  
Дата: 03.04.12 08:18
Оценка: 1 (1)
Здравствуйте, nettro, Вы писали:

N>По поводу отсутствия в программе IPv6, я пока ограничился IPv4 ибо он используется в 98% случаев


Вы на будущее учтите также еще то, что не все сети имеют класс /24, т.е. маску 255.255.255.0. Вполне нормально себе, к примеру, существуют сети /27, т.е. 255.255.255.224. В них сама подсеть может иметь, к примеру, адрес 192.168.1.32, диапазон адресов хостов этой подсети будет 192.168.1.33-192.168.1.62, а широковещательный адрес будет 192.168.1.63. Возможны и другие маски. То есть алгоритм обхода узлов локальной подсети. следовательно, надо улучшить.

N>По поводу функции WmiInfo, как Вы могли заметить, в коде описания кнопочки запуска, есть закомментированная строчка вызова WmiINfo:

N>с самого начала WmiInfo запускалось там, перенос её вызова в funkPingCompleted было тестом, для оценки изменится ли время выполнения или нет.

Так обращение к WMI удаленного компьютера должно происходить только при успешном пинге. А если раскоментировать эту строчку, то получится, что вы будете обходить все компьютеры в любом случае, независимо от результатов пинга. Кроме того, вызов WmiInfo в этом случае остается абсолютно четко в UI-потоке.

F>>Короче, вызов WmiInfo надо выносить в рабочий поток. Для этого не обязательно использовать BackgroundWorker. Можно воспользоваться методом ThreadPool.QueueUserWorkItem:

N>не могли бы Вы подсказать, как правильнее поступить с функцией WmiInfo, вынести приведённый Вами кусочек кода это в отдельную функцию или вставить этот код в обработку кнопки запуска программы, или же оставить её в этом где она находится на данных момент?

Ну вот на том месте, где WmiInfo вызывается сейчас, в funkPingCompleted, и вставить эту строчку (заменить прямой вызов WmiInfo на постановку вызова WmiInfo в очередь пулу потоков). Закомментировать в WmiInfo обращения к richTextBox1 и другим контролам, если они там есть, а в конце WmiInfo поставить:

BeginInvoke(((Action)(() => richTextBox1.Text += string.Format("WmiInfo of {0} done.", a))));


, в обработчик catch то же самое, только вывести, к примеру, Exception.Message. Увидеть как все работает.

N>Что касается richTextBox1, я пока не знаю временно это или оставить его, но в дальнейшем я планирую как то всё эти данные полученные с компьютеров записывать в базу и в следствии этого хотелось бы узнать узнать мнение с высоты Вашего опыта, как это лучше организовать?


Оставьте пока. Надо только строку для вывода копить в WmiInfo в локальной переменной, а вывод в richTextBox1 сделать один раз в самом конце этого метода. А вообще, я бы порекомендовал отделить функционал по сбору информации с компьютеров от UI, выделив этот функционал в отдельный класс. Если интересно, чуть позже напишу как именно.
Re[10]: Оптимизация кода программы
От: nettro  
Дата: 03.04.12 08:36
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>Вы на будущее учтите также еще то, что не все сети имеют класс /24, т.е. маску 255.255.255.0. Вполне нормально себе, к примеру, существуют сети /27, т.е. 255.255.255.224. В них сама подсеть может иметь, к примеру, адрес 192.168.1.32, диапазон адресов хостов этой подсети будет 192.168.1.33-192.168.1.62, а широковещательный адрес будет 192.168.1.63. Возможны и другие маски. То есть алгоритм обхода узлов локальной подсети. следовательно, надо улучшить.


я планировал добавить ещё 2 обычных textBox-а, в которые вводился бы интересующий диапазон адресов и по ним происходил бы обход. Не сделал этого из-за очевидных причин, пока пытаюсь заставить работать то что есть)
Не знаю, решит ли это проблему с масками как вы правильно заметили, но пока мыслей по улучшению алгоритма обхода нет

F>Так обращение к WMI удаленного компьютера должно происходить только при успешном пинге. А если раскоментировать эту строчку, то получится, что вы будете обходить все компьютеры в любом случае, независимо от результатов пинга. Кроме того, вызов WmiInfo в этом случае остается абсолютно четко в UI-потоке.


F>>>Короче, вызов WmiInfo надо выносить в рабочий поток. Для этого не обязательно использовать BackgroundWorker. Можно воспользоваться методом ThreadPool.QueueUserWorkItem:

N>>не могли бы Вы подсказать, как правильнее поступить с функцией WmiInfo, вынести приведённый Вами кусочек кода это в отдельную функцию или вставить этот код в обработку кнопки запуска программы, или же оставить её в этом где она находится на данных момент?

F>Ну вот на том месте, где WmiInfo вызывается сейчас, в funkPingCompleted, и вставить эту строчку (заменить прямой вызов WmiInfo на постановку вызова WmiInfo в очередь пулу потоков). Закомментировать в WmiInfo обращения к richTextBox1 и другим контролам, если они там есть, а в конце WmiInfo поставить:


F>
F>BeginInvoke(((Action)(() => richTextBox1.Text += string.Format("WmiInfo of {0} done.", a))));
F>


F>, в обработчик catch то же самое, только вывести, к примеру, Exception.Message. Увидеть как все работает.

Спасибо сейчас попробую так сделать.

F>Оставьте пока. Надо только строку для вывода копить в WmiInfo в локальной переменной, а вывод в richTextBox1 сделать один раз в самом конце этого метода. А вообще, я бы порекомендовал отделить функционал по сбору информации с компьютеров от UI, выделив этот функционал в отдельный класс. Если интересно, чуть позже напишу как именно.

Если Вас не затруднит буду очень Вам благодарен!!
Re[7]: Оптимизация кода программы
От: motormanyak Земля  
Дата: 03.04.12 08:50
Оценка: 1 (1)
Здравствуйте, Fortnum, Вы писали:

F>А как предусмотреть? Не вызывать EndInvoke, а ждать Callback


а что делать, если Callback никогда не придет? получается у нас один поток будет висеть. а чтоб Callback пришел, надо чтоб функция когда-то закончила выполнение. у него в коде на пинг стоит таймаут 500 мс, так что все будет ок.

Топикстартеру:

твой код не поддается переделке под BackgroundWorker. И вообще я не уверен, что он заработает в несколько потоков. Выводить в richTextBox1 напрямую нельзя как уже говорили раньше. через BeginInvoke тоже не получится, потому что есть вероятность непоследовательного вывода. в конечном итоге получишь мусор, а не результат.
на вскидку:
я бы сделал класс РС со свойствами ip и info. создал коллекцию эти классов. сбор инфы тоже надо вынести в отдельный класс, например InfoCollector. и в конце (у тебя 4 framework):

List<PC> listOfAvailablePCs = //пингуем комп и добавляем в список если он доступен
BackgroundWorker bw = new BackgroundWorker();
bw.RunWorkerCompleted += ....
bw.ProgressChanged += ...
int pcFinishedCount = 0;

bw.DoWork += (sender, args) =>
listOfAvailablePCs.AsParallel().ForAll( (pc)=>
{
//may ping here
InfoCollector.CollectInfo(pc);
Interlocked.Increment(ref pcFinishedCount);
bw.ReportProgress(pcFinishedCount);
};
bw.RunWorkerAsync();


здесь можно пинговать внутри Actoin, но пинг при этом должен быть синхронным, а в класс PC нужно добавить свойство Boolean Available. получиться как-то так:

...
bw.DoWork += (sender, args) =>
listOfAvailablePCs.AsParallel().ForAll( (pc)=>
{
if (PingSync(pc))
{
pc.Available = true;
InfoCollector.CollectInfo(pc);
Interlocked.Increment(ref pcFinishedCount);
}
else
pc.Available = false;
bw.ReportProgress(pcFinishedCount);
};
...
In God We Trust
Re[8]: Оптимизация кода программы
От: nettro  
Дата: 03.04.12 10:54
Оценка:
Здравствуйте, motormanyak, Вы писали:

M>твой код не поддается переделке под BackgroundWorker. И вообще я не уверен, что он заработает в несколько потоков. Выводить в richTextBox1 напрямую нельзя как уже говорили раньше. через BeginInvoke тоже не получится, потому что есть вероятность непоследовательного вывода. в конечном итоге получишь мусор, а не результат.


Я знал что мой код кривой, но не думал что он безнадёжен... Эх.. Не одну неделю гугли, читал, писал, а в итоге всё равно видать придётся в 3-ий раз переписывать проект с 0...

Извиняюсь за наглость, но не могли бы Вы прокомментировать кусочки приведённого вами кода, с небольшими пояснениями на местах многоточий, а то как Вы уже успели заметить у меня со своим то кодом беда, а чужой для меня это как информативные, но непонятные иероглифы)

M>здесь можно пинговать внутри Actoin, но пинг при этом должен быть синхронным, а в класс PC нужно добавить свойство Boolean Available. получиться как-то


Извините за глупые вопросы, не очень понял внутри какого Action? И использование синхронного пинга, разве не увеличит время выполнения программы? (не исключаю, что эти глупые вопросы, из-за не совсем точного понимания приведённых Вами кусочков кода)
Re[9]: Оптимизация кода программы
От: motormanyak Земля  
Дата: 03.04.12 13:03
Оценка: 1 (1)
Здравствуйте, nettro, Вы писали:

N>Здравствуйте, motormanyak, Вы писали:


M>>твой код не поддается переделке под BackgroundWorker. И вообще я не уверен, что он заработает в несколько потоков. Выводить в richTextBox1 напрямую нельзя как уже говорили раньше. через BeginInvoke тоже не получится, потому что есть вероятность непоследовательного вывода. в конечном итоге получишь мусор, а не результат.


N>Я знал что мой код кривой, но не думал что он безнадёжен... Эх.. Не одну неделю гугли, читал, писал, а в итоге всё равно видать придётся в 3-ий раз переписывать проект с 0...


N>Извиняюсь за наглость, но не могли бы Вы прокомментировать кусочки приведённого вами кода, с небольшими пояснениями на местах многоточий, а то как Вы уже успели заметить у меня со своим то кодом беда, а чужой для меня это как информативные, но непонятные иероглифы)


ща попробую.


List<PC> listOfAvailablePCs = //пингуем комп и добавляем в список если он доступен
BackgroundWorker bw = new BackgroundWorker();
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
int pcFinishedCount = 0;

bw.DoWork += (sender, args) =>
listOfAvailablePCs.AsParallel().ForAll( (pc)=>
{
//may ping here
InfoCollector.CollectInfo(pc);
Interlocked.Increment(ref pcFinishedCount);
bw.ReportProgress(pcFinishedCount);
});
bw.RunWorkerAsync();

        void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
//в этом месте процесс опроса завершен. можем вывести какое-нибудь сообщение, типа
MessageBox.Show("Yahoooo!!!!");
//но лучше сделать как предлагает [url=http://msdn.microsoft.com/ru-ru/library/system.componentmodel.backgroundworker.runworkercompleted.aspx]msdn[/url]
//не забываем, что этот метод выполняется в основном потоке, поэтому можем смело вызывать элементы управления если нужно
        }

        void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            //этот метод тоже выполняется потоке UI
this.progressBar1.Value = Math.Round(e.ProgressPercentage / hostsCount * 100);
//hostsCount - общее количество пингуемых серверов
//Math.Round(e.ProgressPercentage / hostsCount * 100) - считаем процент обработанных серверов
        }


N>Извините за глупые вопросы, не очень понял внутри какого Action? И использование синхронного пинга, разве не увеличит время выполнения программы? (не исключаю, что эти глупые вопросы, из-за не совсем точного понимания приведённых Вами кусочков кода)


метод ForAll() принимает Action<T> action как параметр. значит все что находится в скобках этого метода и есть Action. Теперь, так как стоит AsParallel(), значит все Action'ы будут выполнятся в разных потоках (не совсем так, но для первого знакомства сойдет). а так как каждый Action выполняется в отдельном потоке, то и синхронный пинг тормозить нас не будет. во втором куске кода показано все тоже самое, что и выше (точки поставил, чтоб не копировать повторяющийся код). изменяется только Action, а список listOfAvailablePCs должен содержать не доступные компы, а все возможные. в этом случае метод bw_RunWorkerCompleted можно изменить так:

        void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
    if (e.Error != null)
    {
        MessageBox.Show(e.Error.Message);
    }
    else if (e.Cancelled)
    {
        richTextBox1.Text = "Canceled";
    }
    else
    {
       foreach (PC pc in listOfAvailablePCs)
{
if (pc.Available)
 richTextBox1.Text += pc.Info + "\r\n";
else
 richTextBox1.Text += pc.Ip + " is not available\r\n";
}
    }
        }


P.S. все функции Win32_lalala (которые теперь находятся в отдельном классе) должны писать результат в pc.Info, а не в richTextBox1.
P.S.S. catch метода WmiInfo тоже не должен ничего делать с richTextBox1. информацию об ошибке лучше хранить в объекте pc. (например добавить ему еще одно свойство типа Exception)
In God We Trust
Re[2]: Оптимизация кода программы
От: Vladek Россия Github
Дата: 03.04.12 17:32
Оценка:
Здравствуйте, motormanyak, Вы писали:

M>Здесь BackgroundWorker не совсем подходит. В него можно вынести цикл опроса, что разлочит главное окно, но не ускорит процесс выполнения. Чтобы ускорить процесс выполнения, каждую итерацию следует вынести в отдельный поток (класс Thread).


А как же Parallel LINQ, Task Parallel Library, async/await наконец? Мы не ищем лёгких путей, да?
Re[10]: Оптимизация кода программы
От: nettro  
Дата: 03.04.12 18:52
Оценка:
Здравствуйте, motormanyak, Вы писали:

M>ща попробую.


M>
M>List<PC> listOfAvailablePCs = //пингуем комп и добавляем в список если он доступен
M>BackgroundWorker bw = new BackgroundWorker();
M>bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
M>bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
M>int pcFinishedCount = 0;

M>bw.DoWork += (sender, args) =>
M>listOfAvailablePCs.AsParallel().ForAll( (pc)=>
M>{
M>//may ping here
M>InfoCollector.CollectInfo(pc);
M>Interlocked.Increment(ref pcFinishedCount);
M>bw.ReportProgress(pcFinishedCount);
M>});
M>bw.RunWorkerAsync();

M>        void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
M>        {
M>//в этом месте процесс опроса завершен. можем вывести какое-нибудь сообщение, типа
M>MessageBox.Show("Yahoooo!!!!");
M>//но лучше сделать как предлагает [url=http://msdn.microsoft.com/ru-ru/library/system.componentmodel.backgroundworker.runworkercompleted.aspx]msdn[/url]
M>//не забываем, что этот метод выполняется в основном потоке, поэтому можем смело вызывать элементы управления если нужно
M>        }

M>        void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
M>        {
M>            //этот метод тоже выполняется потоке UI
M>this.progressBar1.Value = Math.Round(e.ProgressPercentage / hostsCount * 100);
M>//hostsCount - общее количество пингуемых серверов
M>//Math.Round(e.ProgressPercentage / hostsCount * 100) - считаем процент обработанных серверов
M>        }
M>


N>>Извините за глупые вопросы, не очень понял внутри какого Action? И использование синхронного пинга, разве не увеличит время выполнения программы? (не исключаю, что эти глупые вопросы, из-за не совсем точного понимания приведённых Вами кусочков кода)


M>метод ForAll() принимает Action<T> action как параметр. значит все что находится в скобках этого метода и есть Action. Теперь, так как стоит AsParallel(), значит все Action'ы будут выполнятся в разных потоках (не совсем так, но для первого знакомства сойдет). а так как каждый Action выполняется в отдельном потоке, то и синхронный пинг тормозить нас не будет. во втором куске кода показано все тоже самое, что и выше (точки поставил, чтоб не копировать повторяющийся код). изменяется только Action, а список listOfAvailablePCs должен содержать не доступные компы, а все возможные. в этом случае метод bw_RunWorkerCompleted можно изменить так:


M>
M>        void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
M>        {
M>    if (e.Error != null)
M>    {
M>        MessageBox.Show(e.Error.Message);
M>    }
M>    else if (e.Cancelled)
M>    {
M>        richTextBox1.Text = "Canceled";
M>    }
M>    else
M>    {
M>       foreach (PC pc in listOfAvailablePCs)
M>{
M>if (pc.Available)
M> richTextBox1.Text += pc.Info + "\r\n";
M>else
M> richTextBox1.Text += pc.Ip + " is not available\r\n";
M>}
M>    }
M>        }
M>


M>P.S. все функции Win32_lalala (которые теперь находятся в отдельном классе) должны писать результат в pc.Info, а не в richTextBox1.

M>P.S.S. catch метода WmiInfo тоже не должен ничего делать с richTextBox1. информацию об ошибке лучше хранить в объекте pc. (например добавить ему еще одно свойство типа Exception)

Огромное Вам спасибо за пояснения!! И отдельное спасибо за ответ на возможно глупый вопрос и объяснение Action, а не отсылание на ресурсы msdn из которых для меня пока понятны не все вещи.

Здравствуйте, Vladek, Вы писали:

V>А как же Parallel LINQ, Task Parallel Library, async/await наконец? Мы не ищем лёгких путей, да?


Извините, но к сожаления я вообще не понимаю, о чём Вы написали, т.к. знаком с c# и программирование в частности, если Вы могли заметить по теме достаточно условно...
Я теперь даже не знаю с какой стороны подходить для полного переписывания проекта, и собственно как его переписывать, с моими ограниченными знаниями... А то что Вы упомянули, уверен ещё страшнее уже имеющегося
Re: Оптимизация кода программы
От: Vladek Россия Github
Дата: 03.04.12 19:02
Оценка: 1 (1)
Здравствуйте, nettro, Вы писали:

N>p.s. Если кто то откликнется на тему и поможет на конкретном примере привязать BackgroundWorker и ProgressBar к проге, а то сколько не пытаюсь по статьям с msdn, как то пока не получается... По необходимости могу прислать проект с кодом.


Автор, изучай Parallel LINQ, Task Parallel Library и async/await — это позволит писать тебе очень лаконичный код, особо не заморачиваясь низкоуровневыми деталями. И уж точно не придётся вникать в допотопные BackgroundWorker-ы. Под катом отрефакторенная версия твоего кода, мои дополнительные комментарии начинаются с //NOTE:.

ProgressBar тут попробуй привязать сам, через Invoke.

  Скрытый текст
using System;
using System.Linq;
using System.Management;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace test
{
    public partial class infoNetworkForm : Form
    {
        public infoNetworkForm()
        {
            InitializeComponent();
            пароль_textBox.UseSystemPasswordChar = true;
        }

        private void сканироватьСеть_button_Click(object sender, EventArgs e)
        {
            //NOTE: Запускаем код асинхронно, не блокируя UI-поток своей работой
            //NOTE: но загодя блокируем кнопку сканирования, чтобы пользователь снова её не нажал и не запустил процесс ещё раз
            сканироватьСеть_button.Enabled = false;

            Task.Factory.StartNew(delegate
            {
                // Получаем имя хоста текущей машины
                var localHostName = Dns.GetHostName();

                // Получаем IP машины по имени хоста, 
                //NOTE: при этом ищем IPv4, так как сеть может поддерживать и IPv6
                var localHostIP = Dns.GetHostEntry(localHostName).AddressList.FirstOrDefault(address => address.AddressFamily == AddressFamily.InterNetwork);

                // создаем список для адресов удаленных машин типа string
                //NOTE: не используем примитивные типы без лишней необходимости! Формируем список из объектов IPAddress.
                var remoteHostIPAddresses = Enumerable
                    // повторяем ip-адрес 255 раз
                    .Repeat(localHostIP.GetAddressBytes(), 255)
                    // и преобразуем в обект IPAddress, заменяя последний байт адреса на порядковый номер в последовательности
                    .Select((address, index) =>
                    {
                        address[3] = (byte)(index + 1);
                        return new IPAddress(address);
                    })
                    // формируем из последовательности обыкновенный массив
                    .ToArray();

                //NOTE: запускаем параллельный цикл опроса адресов, тем не менее этот вызов возвратит управление обратно,
                // когда все адреса будут обработаны, то есть дождётся завершения всех итераций.

                Parallel.ForEach(remoteHostIPAddresses, remoteHostIPAddress =>
                {
                    //NOTE: Избавляемся от асинхронных вызовов внутри asinhroPing, так как опрос каждого хоста и так будет совершаться в фоновом потоке
                    asinhroPing(remoteHostIPAddress);
                });
            }, TaskCreationOptions.LongRunning) //NOTE: указываем, что задача может занять длительное время - тогда TPL оптимальнее будет использовать свои ресурсы
                //NOTE: после выполнения задачи - проверим статус выполнения
            .ContinueWith(scanTask =>
            {

                this.Invoke(new Action(delegate
                {
                    //NOTE: разблокируем кнопку
                    сканироватьСеть_button.Enabled = true;
                }));

                //NOTE: если задача сканирования почему-то дала сбой
                if (scanTask.IsFaulted)
                {
                    //NOTE: выводим информацию об ошибке, не забывая сделать это в контексте UI-потока
                    this.Invoke(new Action(delegate
                    {
                        richTextBox1.AppendText("Ошибка! (в функции сканироватьСеть_button_Click)\r\n");
                        richTextBox1.AppendText(
                            "Source: " + scanTask.Exception.Source + "\r\n" +
                            "Message: " + scanTask.Exception.Message + "\r\n" +
                            "HelpLink" + scanTask.Exception.HelpLink);
                    }));
                }
            });
        }

        private void asinhroPing(IPAddress ipAddress)
        {
            try
            {
                // создаём класс управления событиями в потоке
                AutoResetEvent waiter = new AutoResetEvent(false);
                // записываем в массив байт сконвертированную в байтовый массив строку для отправки в пинг запросе
                byte[] buffer = Encoding.ASCII.GetBytes("test asyncPing");
                //создаем класс пинг
                Ping ping = new Ping();
                //указываем на метод, который будет выполняться в результате получения ответа на асинхронный запрос пинга
                //NOTE: больше не требуется, смотри комментарии выше
                //ping.PingCompleted += new PingCompletedEventHandler(funkPingCompleted);

                //выставляем опции для пинга (непринципиально)
                PingOptions options = new PingOptions(64, true);
                int timeout = 500;
                //посылаем асинхронный пинг на адрес с таймаутом 500мс, в нем передаем массив байт сконвертированных их строки в начале кода, используем при передаче указанные опции, после обращаемся к классу управления событиями
                var pingReply = ping.Send(ipAddress, timeout, buffer, options);

                if (pingReply.Status == IPStatus.Success)
                {
                    this.Invoke(new Action(delegate
                    {
                        // если ip адрес пингуеться, выводим ip в richTextBox1
                        richTextBox1.Text += pingReply.Address.ToString() + "\r\n";

                        // если ip адрес пингуеться, передаём этот ip в функция WmiInfo

                        //NOTE: по идее этот метод не должен напрямую обращаться к контролам, чтобы не блокировать UI работой к нему не относящийся,
                        // а просто собрать всю нужную информацию и уже затем передать её в UI-поток для вывода.

                        WmiInfo(pingReply.Address.ToString());
                    }));
                }
            }
            catch (Exception ex)
            {
                this.Invoke(new Action(delegate
                {
                    richTextBox1.AppendText("Ошибка! (в функции asinhroPing)\r\n");
                    richTextBox1.AppendText("Source: " + ex.Source + "\r\n" + "Message: " + ex.Message + "\r\n" + "HelpLink" + ex.HelpLink);
                }));
            }
        }

        private void WmiInfo(string a)
        {
            try
            {
                // Опции, если компьютер не в домене или у Вас нету прав Администратора
                ConnectionOptions options = new ConnectionOptions();
                ManagementScope scope;
                //если на элементе checkBox чтоит галочка, записываем в свойства options значения логина и пароля их textBox-ов
                if (авторизацияСПравамиАдминистратора_checkBox.Checked == true)
                {
                    options.Username = имяПользователя_textBox.Text;
                    options.Password = пароль_textBox.Text;
                    //ManagementScope scope = new ManagementScope("\\\\" + a + "\\root\\cimv2", options);
                    scope = new ManagementScope("\\\\" + a + "\\root\\cimv2", options);
                }
                else
                {
                    //ManagementScope scope = new ManagementScope("\\\\" + a + "\\root\\cimv2");
                    scope = new ManagementScope("\\\\" + a + "\\root\\cimv2");
                }

                //ManagementScope scope = new ManagementScope("\\\\" + a + "\\root\\cimv2", options);
                scope.Connect();

                richTextBox1.Text += "=============== Информация о процессоре ===============\r\n";
                Win32_Processor(scope);
                richTextBox1.Text += "=============== Информация о ОЗУ ===============\r\n";
                Win32_PhysicalMemory(scope);
                richTextBox1.Text += "=============== Информация о жёстких дисках ===============\r\n";
                Win32_DiskDrive(scope);
                richTextBox1.Text += "=============== Информация о видеоадаптере ===============\r\n";
                Win32_VideoController(scope);
            }
            catch (Exception ex)
            {
                richTextBox1.Text += "Ошибка в функции WmiInfo! на ip: " + a + "\r\n";
                richTextBox1.Text += "Source: " + ex.Source + "\r\n" + "Message: " + ex.Message + "\r\n" + "HelpLink" + ex.HelpLink;
            }
        }

        // Класс Win32_Processor предоставляет сведения о процессоре.
        public void Win32_Processor(ManagementScope tmpAddress)
        {
            ObjectQuery query_Win32_Processor = new ObjectQuery("SELECT * FROM Win32_Processor");
            ManagementObjectSearcher searcher_Win32_Processor = new ManagementObjectSearcher(tmpAddress, query_Win32_Processor);
            ManagementObjectCollection queryCollection_Win32_Processor = searcher_Win32_Processor.Get();

            foreach (ManagementObject info_Win32_Processor in queryCollection_Win32_Processor)
            {
                richTextBox1.Text += "------------------------------\r\n";
                richTextBox1.Text += "ID устройства:\t\t" + info_Win32_Processor["DeviceID"] + "\r\n";
                richTextBox1.Text += "Имя:\t\t\t" + info_Win32_Processor["Name"] + "\r\n";
                richTextBox1.Text += "Производитель:\t\t" + info_Win32_Processor["Manufacturer"] + "\r\n";
                richTextBox1.Text += "Описание:\t\t" + info_Win32_Processor["Description"] + "\r\n";
                richTextBox1.Text += "Тип сокета:\t\t" + info_Win32_Processor["SocketDesignation"] + "\r\n";
                richTextBox1.Text += "Текущая частота (MHz):\t" + info_Win32_Processor["CurrentClockSpeed"] + "\r\n";
                richTextBox1.Text += "Версия:\t\t\t" + info_Win32_Processor["Version"] + "\r\n";
                richTextBox1.Text += "Размер L2 кэша (Kb):\t" + info_Win32_Processor["L2CacheSize"] + "\r\n";
                richTextBox1.Text += "Скорость L2 кэша (MHz):\t" + info_Win32_Processor["L2CacheSpeed"] + "\r\n";
                //richTextBox1.Text += "Архитектура:\t\t" + info_Win32_Processor["Architecture"] + "\r\n";
                // в переменную типа строка architecture записываем значение из коллекции
                string architecture = info_Win32_Processor["Architecture"].ToString();
                // преобразуем строку в число и в зависимости от числа будет выведен рузельтат
                switch (System.Int32.Parse(architecture))
                {
                    case 0: richTextBox1.Text += "Архитектура:\t\t" + "x86" + "\r\n";
                        break;
                    case 1: richTextBox1.Text += "Архитектура:\t\t" + "MIPS" + "\r\n";
                        break;
                    case 2: richTextBox1.Text += "Архитектура:\t\t" + "Alpha" + "\r\n";
                        break;
                    case 3: richTextBox1.Text += "Архитектура:\t\t" + "PowerPC" + "\r\n";
                        break;
                    case 6: richTextBox1.Text += "Архитектура:\t\t" + "ia64" + "\r\n";
                        break;
                }
                //richTextBox1.Text += "Состояние:\t\t" + info_Win32_Processor["Availability"] + "\r\n";
                // в переменную типа строка availability записываем значение из коллекции
                string availability = info_Win32_Processor["Availability"].ToString();
                // преобразуем строку в число и в зависимости от числа будет выведен рузельтат
                switch (System.Int32.Parse(availability))
                {
                    case 3: richTextBox1.Text += "Состояние:\t\t" + "Running/Full Power" + "\r\n";
                        break;
                    case 4: richTextBox1.Text += "Состояние:\t\t" + "Warning" + "\r\n";
                        break;
                    case 5: richTextBox1.Text += "Состояние:\t\t" + "Testing" + "\r\n";
                        break;
                    case 10: richTextBox1.Text += "Состояние:\t\t" + "Degradation" + "\r\n";
                        break;
                    case 13: richTextBox1.Text += "Состояние:\t\t" + "Power Save - Unknow" + "\r\n";
                        break;
                    case 14: richTextBox1.Text += "Состояние:\t\t" + "Power Save - Low Power Mode" + "\r\n";
                        break;
                    case 15: richTextBox1.Text += "Состояние:\t\t" + "Power Save - Standby" + "\r\n";
                        break;
                    case 17: richTextBox1.Text += "Состояние:\t\t" + "Power Save - Warning" + "\r\n";
                        break;
                }
                richTextBox1.Text += "Процент загрузки (%):\t" + info_Win32_Processor["LoadPercentage"] + "\r\n";
                richTextBox1.Text += "Статус:\t\t\t" + info_Win32_Processor["Status"] + "\r\n";
                richTextBox1.Text += "------------------------------\r\n";
            }
        }

        // Класс Win32_PhysicalMemory предоставляет сведения о физической памяти.
        public void Win32_PhysicalMemory(ManagementScope tmpAddress)
        {
            ObjectQuery query_Win32_PhysicalMemory = new ObjectQuery("SELECT * FROM Win32_PhysicalMemory");
            ManagementObjectSearcher searcher_Win32_PhysicalMemory = new ManagementObjectSearcher(tmpAddress, query_Win32_PhysicalMemory);
            ManagementObjectCollection queryCollection_Win32_PhysicalMemory = searcher_Win32_PhysicalMemory.Get();

            foreach (ManagementObject info_Win32_PhysicalMemory in queryCollection_Win32_PhysicalMemory)
            {
                richTextBox1.Text += "Наименование устройства:\t" + info_Win32_PhysicalMemory["Name"] + "\r\n";
                richTextBox1.Text += "Слот размещения:\t\t" + info_Win32_PhysicalMemory["DeviceLocator"] + "\r\n";
                // т.к. Capacity показывает общий объем физической памяти в байтах
                long size_in_MB = Int64.Parse(info_Win32_PhysicalMemory["Capacity"].ToString());
                // переводим число из байт в мегабайты
                size_in_MB = size_in_MB / (1024 * 1024);
                richTextBox1.Text += "Объём памяти (Mb):\t" + size_in_MB + "\r\n";
                richTextBox1.Text += "Быстродейсвтие (ns):\t" + info_Win32_PhysicalMemory["Speed"] + "\r\n";
            }
        }

        public void Win32_DiskDrive(ManagementScope tmpAddress)
        {
            ObjectQuery query_Win32_DiskDrive = new ObjectQuery("SELECT * FROM Win32_DiskDrive");
            ManagementObjectSearcher searcher_Win32_DiskDrive = new ManagementObjectSearcher(tmpAddress, query_Win32_DiskDrive);
            ManagementObjectCollection queryCollection_Win32_DiskDrive = searcher_Win32_DiskDrive.Get();

            foreach (ManagementObject info_Win32_DiskDrive in queryCollection_Win32_DiskDrive)
            {
                richTextBox1.Text += "Описание:\t\t" + info_Win32_DiskDrive["Description"] + "\r\n";
                richTextBox1.Text += "Производитель:\t\t" + info_Win32_DiskDrive["Manufacturer"] + "\r\n";
                richTextBox1.Text += "Модель:\t\t\t" + info_Win32_DiskDrive["Model"] + "\r\n";
                richTextBox1.Text += "Идентификатор диска:\t" + info_Win32_DiskDrive["DeviceID"] + "\r\n";
                richTextBox1.Text += "Тип интерфеса:\t\t" + info_Win32_DiskDrive["InterfaceType"] + "\r\n";
                richTextBox1.Text += "Тип носителя:\t\t" + info_Win32_DiskDrive["MediaType"] + "\r\n";
                richTextBox1.Text += "Колличество разделов:\t" + info_Win32_DiskDrive["Partitions"] + "\r\n";
            }
        }

        public void Win32_VideoController(ManagementScope tmpAddress)
        {
            ObjectQuery query_Win32_VideoController = new ObjectQuery("SELECT * FROM Win32_VideoController");
            ManagementObjectSearcher searcher_Win32_VideoController = new ManagementObjectSearcher(tmpAddress, query_Win32_VideoController);
            ManagementObjectCollection queryCollection_Win32_VideoController = searcher_Win32_VideoController.Get();

            foreach (ManagementObject info_Win32_VideoController in queryCollection_Win32_VideoController)
            {

                richTextBox1.Text += "Описание:\t\t" + info_Win32_VideoController["Description"] + "\r\n";
                richTextBox1.Text += "Видеопроцессор:\t\t" + info_Win32_VideoController["VideoProcessor"] + "\r\n";
                // т.к. AdapterRAM показывает общий объем графической памяти в байтах, конвертируем строку в инт и присваевыем переменной
                long size_AdapterRAM_in_MB = Int64.Parse(info_Win32_VideoController["AdapterRAM"].ToString());
                // переводим число из байт в мегабайты
                size_AdapterRAM_in_MB = size_AdapterRAM_in_MB / (1024 * 1024);
                richTextBox1.Text += "Объём памяти (Mb):\t" + size_AdapterRAM_in_MB + "\r\n";
                richTextBox1.Text += "Версия драйвера:\t\t" + info_Win32_VideoController["DriverVersion"] + "\r\n";
                richTextBox1.Text += "Вендор:\t\t\t" + info_Win32_VideoController["PNPDeviceID"] + "\r\n";
                // в переменную типа строка videoArchitecture записываем значение из коллекции
                string videoArchitecture = info_Win32_VideoController["VideoArchitecture"].ToString();
                // преобразуем строку в число и в зависимости от числа будет выведен рузельтат
                switch (System.Int32.Parse(videoArchitecture))
                {
                    case 1: richTextBox1.Text += "Архитектура:\t\t" + "Other" + "\r\n";
                        break;
                    case 2: richTextBox1.Text += "Архитектура:\t\t" + "Unknown" + "\r\n";
                        break;
                    case 3: richTextBox1.Text += "Архитектура:\t\t" + "CGA" + "\r\n";
                        break;
                    case 4: richTextBox1.Text += "Архитектура:\t\t" + "EGA" + "\r\n";
                        break;
                    case 5: richTextBox1.Text += "Архитектура:\t\t" + "VGA" + "\r\n";
                        break;
                    case 6: richTextBox1.Text += "Архитектура:\t\t" + "SVGA" + "\r\n";
                        break;
                    case 7: richTextBox1.Text += "Архитектура:\t\t" + "MDA" + "\r\n";
                        break;
                    case 8: richTextBox1.Text += "Архитектура:\t\t" + "HGC" + "\r\n";
                        break;
                    case 9: richTextBox1.Text += "Архитектура:\t\t" + "MCGA" + "\r\n";
                        break;
                    case 10: richTextBox1.Text += "Архитектура:\t\t" + "8514A" + "\r\n";
                        break;
                    case 11: richTextBox1.Text += "Архитектура:\t\t" + "XGA" + "\r\n";
                        break;
                    case 12: richTextBox1.Text += "Архитектура:\t\t" + "Linear Frame Buffer" + "\r\n";
                        break;
                    case 160: richTextBox1.Text += "Архитектура:\t\t" + "PC-98" + "\r\n";
                        break;
                }

            }
        }

        private void авторизацияСПравамиАдминистратора_checkBox_CheckedChanged(object sender, EventArgs e)
        {
            if (авторизацияСПравамиАдминистратора_checkBox.Checked == true)
            {
                имяПользователя_textBox.ReadOnly = false;
                пароль_textBox.ReadOnly = false;
            }
            else
            {
                имяПользователя_textBox.ReadOnly = true;
                имяПользователя_textBox.ReadOnly = true;
            }
        }
    }
}
Re[11]: Оптимизация кода программы
От: Vladek Россия Github
Дата: 03.04.12 19:23
Оценка:
Здравствуйте, nettro, Вы писали:

N>Извините, но к сожаления я вообще не понимаю, о чём Вы написали, т.к. знаком с c# и программирование в частности, если Вы могли заметить по теме достаточно условно...

N>Я теперь даже не знаю с какой стороны подходить для полного переписывания проекта, и собственно как его переписывать, с моими ограниченными знаниями... А то что Вы упомянули, уверен ещё страшнее уже имеющегося

Наоборот, оно проще и лаконичнее. Там пониже, я слегка отрефакторил ваш код — заметьте, почти не трогая ваш код, а лишь обрамляя его в новые конструкции. В этом вся мощь и прелесть TPL и PLINQ.

Как тут правильно заметили, да я и сам там в комментариях к коду упомянул — надо отделить друг от друга две части программы: часть, собирающую информацию, и часть, выводящую её пользователю или записывающую её в БД. Тогда первую часть можно будет распараллелить по-полной, окончательно избавившись от тормозов.
Re[12]: Оптимизация кода программы
От: nettro  
Дата: 03.04.12 20:06
Оценка:
Здравствуйте, Vladek, Вы писали:

V>Здравствуйте, nettro, Вы писали:


N>>Извините, но к сожаления я вообще не понимаю, о чём Вы написали, т.к. знаком с c# и программирование в частности, если Вы могли заметить по теме достаточно условно...

N>>Я теперь даже не знаю с какой стороны подходить для полного переписывания проекта, и собственно как его переписывать, с моими ограниченными знаниями... А то что Вы упомянули, уверен ещё страшнее уже имеющегося

V>Наоборот, оно проще и лаконичнее. Там пониже, я слегка отрефакторил ваш код — заметьте, почти не трогая ваш код, а лишь обрамляя его в новые конструкции. В этом вся мощь и прелесть TPL и PLINQ.


V>Как тут правильно заметили, да я и сам там в комментариях к коду упомянул — надо отделить друг от друга две части программы: часть, собирающую информацию, и часть, выводящую её пользователю или записывающую её в БД. Тогда первую часть можно будет распараллелить по-полной, окончательно избавившись от тормозов.


Огромное спасибо Вам за полностью приведённый, отредактированный код с Вашими пояснениями почти к каждой строке кода, для меня просто неоценима подобного рода информативность.
Сейчас проверил на домашней сети, работа проекта колосально изменилась в лучшую сторону. Завтра буду тестить на работе.

По поводу разделения программы на 2 части, честно говоря для меня это всё одна большая часть, но как уже писали добрые люди в постах ранее, необходимо отделить функции типа public void Win32_ххх от программы и вынести это так сказать за пределы данной формы, как советовали опять таки выше — в отдельный класс. Так вот тут у меня и возникает может не очень корректный вопрос:
обязательно в этом новом классе использовать свойства get и put а само описание Win32_xxx должно находиться ещё где то или ниже, или можно в новом классе описать прям такими функциями какие они есть?
Re[2]: Оптимизация кода программы
От: Fortnum  
Дата: 04.04.12 06:49
Оценка:
Здравствуйте, Vladek, Вы писали:

V>Автор, изучай Parallel LINQ, Task Parallel Library и async/await — это позволит писать тебе очень лаконичный код, особо не заморачиваясь низкоуровневыми деталями. И уж точно не придётся вникать в допотопные BackgroundWorker-ы. Под катом отрефакторенная версия твоего кода, мои дополнительные комментарии начинаются с //NOTE:.

V>ProgressBar тут попробуй привязать сам, через Invoke.

Засада осталась здесь:
private void asinhroPing(IPAddress ipAddress)
{
    ...

    if (pingReply.Status == IPStatus.Success)
    {
        this.Invoke(new Action(delegate
        {
            WmiInfo(pingReply.Address.ToString());
        }));
    }
}
Re[3]: Оптимизация кода программы
От: nettro  
Дата: 04.04.12 07:07
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>Засада осталась здесь:

private void asinhroPing(IPAddress ipAddress)
{
    ...

    if (pingReply.Status == IPStatus.Success)
    {
        this.Invoke(new Action(delegate
        {
            WmiInfo(pingReply.Address.ToString());
        }));
    }
}


Добрый день! А в чём состоит засада и есть ли у неё пути решения?
Re[3]: Оптимизация кода программы
От: motormanyak Земля  
Дата: 04.04.12 07:17
Оценка: +2
Здравствуйте, Vladek, Вы писали:

V>А как же Parallel LINQ, Task Parallel Library, async/await наконец? Мы не ищем лёгких путей, да?


прежде чем трогать PLINQ, TPL и тем более async/await надо сначала разобраться что такое делегаты, потоки, пул потоков и как с этим всем работать, потом можно переходить к LINQ, и только потом к PLINQ и всему остальному. сначала люди пишут велосипеды, а потом используют модные библиотеки. и никак не наоборот
In God We Trust
Re[4]: Оптимизация кода программы
От: Fortnum  
Дата: 04.04.12 07:26
Оценка:
Здравствуйте, nettro, Вы писали:

N>Добрый день! А в чём состоит засада и есть ли у неё пути решения?


Ну так WmiInfo как выполнялось, так и продолжает выполняться в UI-потоке. Рабочий поток после вызова this.Invoke ставит в очередь и ждет, пока UI-поток формы выполнит WmiInfo. Если IP-адрес пингуется, но не поддерживает WMI (это может быть не компьютер, или компьютер под управлением не-Windows), или происходит ошибка аутентификации (на том компьютере не настроен DCOM), то форма будет висеть. Что и происходит у меня. С точки зрения ping'а у вас, было оно сделано допотопно или современно — не важно, все и так было сделано правильно — использование TPL не дало ничего нового. Но изучать его, конечно же, надо. Только я не уверен, что на изучение BackgroundWorker надо забить. Мне кажется, сперва надо научиться пользоваться BackgroundWorker'ом и ThreadPool'ом.

this.Invoke(new Action(delegate
{
    WmiInfo(pingReply.Address.ToString());
}));
Re[5]: Оптимизация кода программы
От: nettro  
Дата: 04.04.12 11:24
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>Если IP-адрес пингуется, но не поддерживает WMI (это может быть не компьютер, или компьютер под управлением не-Windows), или происходит ошибка аутентификации (на том компьютере не настроен DCOM), то форма будет висеть. Что и происходит у меня.


К моему огромнейшему сожалению, это происходит и у меня...((

F>использование TPL не дало ничего нового. Но изучать его, конечно же, надо.


Да изучать по хорошему надо всё с чем работаешь или приходиться работать, но сами понимаете что с этим возникают некие проблемы когда есть какое то ограничение по времени...

Не сочтите за наглость, но если Вы при написании кусочков кода касаемых BackgroundWorker и ThreadPool, писали это в проекте и у Вас получилось избавиться от зависания формы, не могли бы Вы выложить этот проект, а то я смотрю мнения разделились, от чего я запутался ещё больше...
Спасибо.
Re[6]: Оптимизация кода программы
От: nettro  
Дата: 04.04.12 18:30
Оценка:
Здравствуйте, nettro, Вы писали:

N>Здравствуйте, Fortnum, Вы писали:


F>>Если IP-адрес пингуется, но не поддерживает WMI (это может быть не компьютер, или компьютер под управлением не-Windows), или происходит ошибка аутентификации (на том компьютере не настроен DCOM), то форма будет висеть. Что и происходит у меня.


N>К моему огромнейшему сожалению, это происходит и у меня...((


F>>использование TPL не дало ничего нового. Но изучать его, конечно же, надо.


N>Да изучать по хорошему надо всё с чем работаешь или приходиться работать, но сами понимаете что с этим возникают некие проблемы когда есть какое то ограничение по времени...


N>Не сочтите за наглость, но если Вы при написании кусочков кода касаемых BackgroundWorker и ThreadPool, писали это в проекте и у Вас получилось избавиться от зависания формы, не могли бы Вы выложить этот проект, а то я смотрю мнения разделились, от чего я запутался ещё больше...

N>Спасибо.

Если ещё кто то отзовётся на тему, этот вопрос не оставьте без внимания

N>По поводу разделения программы на 2 части, честно говоря для меня это всё одна большая часть, но как уже писали добрые люди в постах ранее, необходимо отделить функции типа public void Win32_ххх от программы и вынести это так сказать за пределы данной формы, как советовали опять таки выше — в отдельный класс. Так вот тут у меня и возникает может не очень корректный вопрос:

обязательно в этом новом классе использовать свойства get и put а само описание Win32_xxx должно находиться ещё где то или ниже, или можно в новом классе описать прям такими функциями какие они есть?
Re[7]: Оптимизация кода программы
От: igor-booch Россия  
Дата: 05.04.12 08:09
Оценка:
F>Не понял, каким образом этот факт влияет на выбор между использованием BackgroundWorker'а и запуском отдельного Thread'а?

Ну не нужна автору кнопка Stop pinging, а Abort треда, который выполняет пинг не приводит нарушению целостности. Зачем ему тратить время и вникать в BackgroundWorker? Я думаю это некая админская тулза для внутреннего использования, я бы сделал простой отдельный тред на каждый пинг.
http://rsdn.ru/Info/rules.xml
Re[8]: Оптимизация кода программы
От: Fortnum  
Дата: 05.04.12 08:16
Оценка:
Здравствуйте, igor-booch, Вы писали:

F>>Не понял, каким образом этот факт влияет на выбор между использованием BackgroundWorker'а и запуском отдельного Thread'а?


IB>Ну не нужна автору кнопка Stop pinging, а Abort треда, который выполняет пинг не приводит нарушению целостности. Зачем ему тратить время и вникать в BackgroundWorker? Я думаю это некая админская тулза для внутреннего использования, я бы сделал простой отдельный тред на каждый пинг.


Все же 254 рабочих потока — это жестоко. Но для того, чтобы въехать в суть происходящего сойдет. Т.к. автору нужно для начала понять, как в richTextBox выводить результаты работы этих потоков, чтобы они не путались между собой.
Re[7]: Оптимизация кода программы
От: motormanyak Земля  
Дата: 05.04.12 08:21
Оценка:
Здравствуйте, nettro, Вы писали:

N>>Не сочтите за наглость, но если Вы при написании кусочков кода касаемых BackgroundWorker и ThreadPool, писали это в проекте и у Вас получилось избавиться от зависания формы, не могли бы Вы выложить этот проект, а то я смотрю мнения разделились, от чего я запутался ещё больше...

N>>Спасибо.

N>Если ещё кто то отзовётся на тему, этот вопрос не оставьте без внимания


Немного не понял, а что конкретно нужно? по-моему уже довольно много кода выложили, чтоб избавиться от зависания.

N>>По поводу разделения программы на 2 части, честно говоря для меня это всё одна большая часть, но как уже писали добрые люди в постах ранее, необходимо отделить функции типа public void Win32_ххх от программы и вынести это так сказать за пределы данной формы, как советовали опять таки выше — в отдельный класс. Так вот тут у меня и возникает может не очень корректный вопрос:

N>обязательно в этом новом классе использовать свойства get и put а само описание Win32_xxx должно находиться ещё где то или ниже, или можно в новом классе описать прям такими функциями какие они есть?

а что за свойства такие get и put? может имелось в виду getter/setter?
можно сделать класс вообще с одним публичным методом возвращающим строку (в зависимости от конкретной задачи).

/*static*/ class GatherInfo
{
public /*static*/ String GetInfo()
{
String result = Win32_Processor();
result += Win32_xxx();
result += Win32_yyy();
//etc
return result;
}

private /*static*/ String Win32_Processor()
{
return [Some info about processor]
}

private /*static*/ String Win32_xxx()
{
return [another info]
}
}


может и не самый лучший способ, но самый простой и почти не требует доработок
In God We Trust
Re[8]: Оптимизация кода программы
От: nettro  
Дата: 05.04.12 09:39
Оценка:
Здравствуйте, motormanyak, Вы писали:

M>Немного не понял, а что конкретно нужно? по-моему уже довольно много кода выложили, чтоб избавиться от зависания.


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

N>>>По поводу разделения программы на 2 части, честно говоря для меня это всё одна большая часть, но как уже писали добрые люди в постах ранее, необходимо отделить функции типа public void Win32_ххх от программы и вынести это так сказать за пределы данной формы, как советовали опять таки выше — в отдельный класс. Так вот тут у меня и возникает может не очень корректный вопрос:

N>>обязательно в этом новом классе использовать свойства get и put а само описание Win32_xxx должно находиться ещё где то или ниже, или можно в новом классе описать прям такими функциями какие они есть?

M>а что за свойства такие get и put? может имелось в виду getter/setter?

M>можно сделать класс вообще с одним публичным методом возвращающим строку (в зависимости от конкретной задачи).

/*static*/ class GatherInfo
{
    public /*static*/ String GetInfo()
    {
        String result = Win32_Processor();
        result += Win32_xxx();
        result += Win32_yyy();
        //etc
        return result;
    }

    private /*static*/ String Win32_Processor()
    {
        return [Some info about processor]
    }

    private /*static*/ String Win32_xxx()
    {
        return [another info]
    }
}


M>может и не самый лучший способ, но самый простой и почти не требует доработок


Извиняюсь, в прошлом сообщении не правильно написал, не свойства get и put, а get и set, что то на подобие этого (взято с wiki):
class MyClass
{
    private int p_field;
    public int Field
    {
        get
        {
            return p_field;
        }
        private set
        {
            p_field = value;
        }
    }
}


Здравствуйте, Fortnum, Вы писали:

F>А вообще, я бы порекомендовал отделить функционал по сбору информации с компьютеров от UI, выделив этот функционал в отдельный класс. Если интересно, чуть позже напишу как именно.


Всё ещё интересует))
Re: Оптимизация кода программы
От: Vladek Россия Github
Дата: 05.04.12 13:10
Оценка:
Здравствуйте, nettro, Вы писали:

N>p.s. Если кто то откликнется на тему и поможет на конкретном примере привязать BackgroundWorker и ProgressBar к проге, а то сколько не пытаюсь по статьям с msdn, как то пока не получается... По необходимости могу прислать проект с кодом.


Вот здесь обновленная версия программы с ProgressBar и без лишних тормозов от частых обращений к UI. Все данные по каждому хосту накапливаются в объекте класса StringBuilder, и только потом его содержимое добавляется в текстовое поле.
Re[2]: Оптимизация кода программы
От: nettro  
Дата: 05.04.12 13:31
Оценка:
Здравствуйте, Vladek, Вы писали:

V>Здравствуйте, nettro, Вы писали:


N>>p.s. Если кто то откликнется на тему и поможет на конкретном примере привязать BackgroundWorker и ProgressBar к проге, а то сколько не пытаюсь по статьям с msdn, как то пока не получается... По необходимости могу прислать проект с кодом.


V>Вот здесь обновленная версия программы с ProgressBar и без лишних тормозов от частых обращений к UI. Все данные по каждому хосту накапливаются в объекте класса StringBuilder, и только потом его содержимое добавляется в текстовое поле.


АААААА!!! Огромнейшее Вам спасибо!! Вы 2ой раз меня выручаете, за что вам большое спасибо!
К сожалению сегодня уже не успею протестировать , дома почитаю код и постараюсь понять, а завтра уже протестирую работу, и отпишусь по поводу работы и кода, не закрывайте пожалуйста пока тему.
Re[2]: Оптимизация кода программы
От: arsen111  
Дата: 06.11.12 07:25
Оценка:
Здравствуйте, Vladek, Вы писали:

V>Здравствуйте, nettro, Вы писали:


N>>p.s. Если кто то откликнется на тему и поможет на конкретном примере привязать BackgroundWorker и ProgressBar к проге, а то сколько не пытаюсь по статьям с msdn, как то пока не получается... По необходимости могу прислать проект с кодом.


V>Вот здесь обновленная версия программы с ProgressBar и без лишних тормозов от частых обращений к UI. Все данные по каждому хосту накапливаются в объекте класса StringBuilder, и только потом его содержимое добавляется в текстовое поле.

Здравствуйте
а если сети которые нужно сканить — разные насколько я понял не пройдет-формируем ведь только последний байт к примеру локальная машина 172.17.2.34 не увидит машину 172.16.2.41 что есть печально.может из списка айпишники тянуть?
Re[3]: Оптимизация кода программы
От: Vladek Россия Github
Дата: 06.11.12 12:05
Оценка:
Здравствуйте, arsen111, Вы писали:

A>Здравствуйте

A>а если сети которые нужно сканить — разные насколько я понял не пройдет-формируем ведь только последний байт к примеру локальная машина 172.17.2.34 не увидит машину 172.16.2.41 что есть печально.может из списка айпишники тянуть?

Да, можно из списка — никаких проблем.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.