Текстовое поле обновляется только после завершения других тем. - PullRequest
1 голос
/ 03 января 2012

В течение нескольких дней я пытался понять, как использовать текстовое поле make console update для его выполнения.Я пришел к выводу, что многопоточность абсолютно необходима для одновременного запуска формы и консольного процесса.Сам процесс является автономной программой, поэтому я использую стандартный вывод, чтобы извлечь из него информацию, и если бы мне не понадобилось обновлять текстовое поле во время его работы, было бы здорово, но проблема в том, что он обновляется только после выполнения процесса.хотя на самом деле я использую многопоточность.

Это начало создания делегата для функции, которая запускает процесс и обрабатывает вывод, а также строку, которую я использую для обмена информацией между потоками и блокировкой:

    private static readonly object _locker = new object();
    volatile string exchange = "";
    delegate void CallDelegate(string filename);

Вот сама функция:

    public void CallConsole(string filename)
    {
        Thread.CurrentThread.Name = "ProccessThread";
        Thread.CurrentThread.IsBackground = false;
        Process p = new Process();
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.RedirectStandardError = true;
        p.StartInfo.FileName = filename;
        if (checkBox1.Checked)
            p.StartInfo.CreateNoWindow = true;
        string output;
        p.Start();
        while (!p.HasExited)
        {
            lock (_locker)
            {
                output = p.StandardError.ReadToEnd();
                if (output.Length != 0)
                {
                    exchange = output;
                    Thread.Sleep(100);
                    MessageBox.Show(output);
                }
                output = p.StandardOutput.ReadToEnd();
                exchange = output;
                System.Threading.Thread.Sleep(100);
            }
        }
    }

И вот выполнение программы после button_click

    private void button1_Click_1(object sender, EventArgs e)
    {
        textBox2.Text = "";
        //Thread.CurrentThread.Name = "Main";
        CallDelegate call = new CallDelegate (CallConsole);
        IAsyncResult tag = call.BeginInvoke(textBox1.Text, null, null);
        button1.IsAccessible = false;
        while (!tag.IsCompleted)
        {
            string temp = "";
            lock (_locker)
            {
                Thread.Sleep(50);
                if (exchange.Length != 0)
                {
                    temp = exchange;
                    exchange = "";
                }
            }
            if (temp.Length != 0)
                textBox2.Text = textBox2.Text + temp;
        }
        call.EndInvoke(tag);
        button1.IsAccessible = true;
    }

Примечание: textbox1 - путь к файлу textbox2 - только для чтения многострочное текстовое поле

Есть идеи, почему его обновление происходит только после CallConsole?

1 Ответ

7 голосов
/ 03 января 2012

Общая проблема : вы зацикливаетесь на button1_Click_1, фактически блокируя поток пользовательского интерфейса. Это предотвращает обработку других событий, включая перерисовку и т. Д.

Ты не должен этого делать; вместо этого, если вы хотите что-то опрашивать, установите таймер для опроса, позволяя пользовательскому интерфейсу обрабатывать события в «простое» время.

Более насущная проблема : вы звоните ReadToEnd читателю из незавершенного процесса. Это будет (я считаю) заблокировать, пока процесс не завершится. (До его завершения читатель не имеет «конца» как такового.) Это означает, что у вас есть один поток, удерживающий блокировку и блокирующий до завершения процесса - и затем вы пытаетесь получить эту блокировку в Пользовательский интерфейс.

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

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