Мониторинг процесса при закрытии C #

У меня проблема со следующим кодом, и я пытаюсь, чтобы процесс, вызывающий ffmpeg , работающий в системе, закрывался, давая предупреждение о завершении работы.

private void btnIniciar_Click(object sender, EventArgs e)
        {
            btnIniciar.Enabled = false;
            btnCancelar.Enabled = true;
            Process p = new Process();
            ProcessStartInfo psi = new ProcessStartInfo("cmd.exe");
            //psi->WindowStyle = ProcessWindowStyle::Hidden;
            psi.Arguments = "/k ffmpeg -i " + txtArchivo.Text + " proceso\\video.mp4";
            p.StartInfo = psi;
            p.Start();
            Thread.Sleep(1000);
            while(procesoFFMPEG())
            {
                lblEstado.Text = "Estado: En ejecucion...";
            }
            lblEstado.Text = "Estado: Finalizado";
            //p.Kill();
        }

public Boolean procesoFFMPEG()
        {
            if(Process.GetProcessesByName("ffmpeg").Length > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

Проблема в том, что при выполнении программы это frizea до тех пор, пока процесс ffmpeg не будет закрыт.

в чем я не прав?

привет

0
задан 16.01.2017, 06:42
0 ответов

Ты блокируешь трэд, который берется за UI, следовательно интерфейс пользователя остается жареным.

Используй один BackgroundWorker, ты будешь должен отделывать это немного, но оно было бы нечто похожим:

private void btnIniciar_Click(object sender, EventArgs e) {
    btnIniciar.Enabled = false;
    btnCancelar.Enabled = true;

    lblEstado.Text = "Estado: En ejecucion...";
    Process p = new Process();
    ProcessStartInfo psi = new ProcessStartInfo("cmd.exe");
    psi.Arguments = "/k ffmpeg -i " + txtArchivo.Text + " proceso\\video.mp4";
    p.StartInfo = psi;
    p.Start();

    var worker = new System.ComponentModel.BackgroundWorker() {
        WorkerReportsProgress = true,
        WorkerSupportsCancellation = true
    };
    btnCancelar.OnClick => (s, a) => worker.CancelAsync();

    worker.DoWork += (s, a) => {
        int n=0;
        while (procesoFFMPEG()) {
            if (worker.CancellationPending) { a.Cancel = true;  break; }
            worker.ReportProgress((n++)%100);
        }
    };
    worker.ProgressChanged += (s, a) => { } 

    worker.RunWorkerCompleted += (s,a) => {
        lblEstado.Text = "Estado: Finalizado";
    }
    worker.RunWorkerAsync();
}

Имей в виду, что код будет работать в другом трэде, и внутри DoWork ты не сможешь соглашаться на элементы интерфейса пользователя, кроме того, что ты используешь метод Invoke form или контроля, на который ты хочешь согласиться, для того, чтобы работал этот код в thread, который манипулирует UI.

control.Invoke((MethodInvoker) (() => control.Text = "new text"));
3
ответ дан 03.12.2019, 17:40

Проблема вероятно находится в твоем цикле while(procesoFFMPEG())... Этот цикл блокирует главный трэд приложения, не позволяет, чтобы UI стал отвечающим совремнным требованиям.

Попытайся помещать внутри этого цикла один Thread.Sleep или один Application.DoEvents(), то, что будет способствовать тому, чтобы у UI было время обрабатывания событий.

Edit

TL; DR; В 99 % случаев, самый правильный способ противостоять этим проблемам - та, что он показывает @Blau в Вашем ответе.

Как хорошо он обозначался @Blau, у DoEvents есть несколько противопоказаний, которые заслуживают того, чтобы быть остроконечными. Смоги вызывать проблему повторного захода, так как, если какое-либо из сообщений, обработанных в течение Вашего выполнения вызывает, что взрывается какое-то событие приложения, могут работать другие части кода и вызывать ошибки, тяжелые для того, чтобы отлаживать. Поэтому Microsoft не рекомендует Ваше использование для операций, которые опаздывали бы много времени. В этих случаях, предпочтительный один BackgroundWorker или использовать async/await.

Как добавочное объяснение, существует дискуссия на если BackgroundWorker он остался, начиная с.Net 4.5, устаревшим. В общем, если мы используем.Net 4.5, есть некое согласие, в котором предпочтительно использовать async/await, прежде всего, если работа, которая должна осуществляться, понимает операции ввода / вывода. Для таких случаев как который он занимает нас, использование BackgroundWorker он правилен.

Однако, и чтобы защищать немного мой ответ, для циклов, которые будут опаздывать совсем небольшое время, DoEvents он верно приемлемый по моему мнению.

1
ответ дан 03.12.2019, 17:40