Как получить список процессов и сохранить их в ListBox, изменяя ListBox при каждом изменении списка процессов - PullRequest
0 голосов
/ 24 ноября 2018

В этой ситуации я пытаюсь добиться эффекта, аналогичного диспетчеру задач.У меня есть форма (называемая MainForm) с ListBox (называемый listBox1) внутри которого я хочу хранить процессы внутри.Каждый раз, когда список процессов изменяется, я хочу, чтобы ListBox автоматически обновлял , чтобы включить новый список процессов (мне не нужно нажимать кнопку для его обновления).

То, что я пробовал до сих пор:

  • Потоки (я либо получаю "Операция кросс-потока недопустима: доступ к элементу управления из потока, отличного от потока, в котором он был создан"ошибка, или она просто ничего не делает или не работает
  • Таймеры (они просто не работают вообще)
  • Циклы do-while (они либо замораживают форму, либо приводят к тому, что она не работает)загрузка вообще)
  • BindedLists (они фактически обновляют ListBox, но они не работают половину времени)
  • События (они не работают вообще)
  • Решения для подобных проблем, найденных на этом сайте
  • Подпрограммы (такие же, как циклы do-while)
  • Рекурсивный вызов функций (То же, что циклы do-while)
  • Создание несколькихразные копии списка процессов и обнаружение, когда один из них меняется (это только становится слишком сложным, запутанным и неэффективнымListBox.Update () (они не очень полезны)

Вот мой код (он на самом деле не нужен, так как я технически запрашиваю код):

Process[] processes = Process.GetProcesses();
foreach (Process proc in processes) {
    if (proc.MainWindowTitle.Length > 0)
    {
        listBox1.Items.Add(item);
    }
}

Заранее спасибо!

РЕДАКТИРОВАТЬ: Некоторые люди предложили мне оглянуться назад на подход Timer.Вот код для этого:

// For this example, I will just set it to update every 1/4th of a second.
public static System.Timers.Timer aTimer = new System.Timers.Timer(250);
public MainForm {
    InitializeComponent(); // Create the form
    aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
    aTimer.Enabled = true;
}

public static void OnTimedEvent(object sender, System.Timers.ElapsedEventArgs e) {
    UpdateList();
}

public void UpdateList {
    listBox1.Items.Clear();
    Process[] processes = Process.GetProcesses();
    foreach (Process proc in processes) {
        if (proc.MainWindowTitle.Length > 0)
        {
            listBox1.Items.Add(item);
        }
    }
}

Я также пробовал другие различные методы, такие как остановка таймера и установка его заново, но они не влияют на это вообще.Как ни странно, большинство техник, которые я уже попробовал, действительно работают в консольном режиме (особенно многопоточность и таймеры. Похоже, они просто не работают в WinForms).

1 Ответ

0 голосов
/ 25 ноября 2018

В проекте WinForms вы в основном загружаете свои формы / элементы управления и возвращаете управление ОС.Ваша программа не будет ничего делать в «основном» потоке, пока что-то не произойдет, например, щелчок мышью, нажатие клавиши или событие таймера.

Таким образом, во время цикла while в «главном» потоке вы не возвращаете контроль над ОС, и ваше приложение, кажется, зависает, поскольку вы не предоставляете ОС возможность даже перекраситьwindow.

Если вы используете System.Threading.Timer, System.Timers.Timer или запускаете свой собственный поток, код не будет выполняться в главном потоке, и вы не сможете напрямую обновлять элементы управления.,Вы можете использовать Control.BeginInvoke, чтобы поставить в очередь сообщение для него.

A System.Windows.Forms.Timer будет"галочкой" в главном потоке.Я предлагаю вам изучить это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...