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ой раз меня выручаете, за что вам большое спасибо!
К сожалению сегодня уже не успею протестировать , дома почитаю код и постараюсь понять, а завтра уже протестирую работу, и отпишусь по поводу работы и кода, не закрывайте пожалуйста пока тему.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.