Richtextbox.invoke, C #, форма все еще висит - PullRequest
1 голос
/ 07 апреля 2009

Я написал приложение на c # для запуска внешней программы и перенаправил его вывод в richtextbox в моей форме. Я создал процесс, используя следующие настройки

p1.StartInfo.RedirectStandardOutput = true;
p1.OutputDataReceived += new DataReceivedEventHandler(outputreceived);

и в полученном событии

void outputreceived(object sender, DataReceivedEventArgs e)
{
  if (!string.IsNullOrEmpty(e.Data))
  {
    richTextBox1.Invoke(new UpdateOutputCallback(this.updateoutput),
                        new object[] { e.Data });
  }
}

void updateoutput(string text)
{
  int len = text.Length;
  int start = richTextBox1.Text.Length;
  richTextBox1.Text += text + Environment.NewLine;
  richTextBox1.Select(start, len);
  richTextBox1.SelectionColor = System.Drawing.Color.White;
  richTextBox1.Select(richTextBox1.Text.Length, 0);
  richTextBox1.ScrollToCaret();
}

Теперь, хотя дело в том, что оно работает, но моя основная форма, которая содержит текстовое поле, зависает, если вывод огромен из приложения. Я думаю, что каждый раз вызов invoke приводит к перерисовке формы, что происходит очень часто. Есть ли альтернатива, чтобы я мог видеть обновления текстового поля по мере их появления, а также сохранять форму полностью активной?

<ч />

Обновление:

Я думаю, что получил ответ, я использовал BeginInvoke, когда я должен был использовать Invoke. <Ч />

Обновление 1:

Я пробовал и BeginInvoke, и Suspendlayout, но это не дает мне желаемой функциональности, происходит то, что процесс восстанавливает весь стандартный вывод в строку, но поток, отвечающий за обновление текста, тратит свое время на распечатать данные. Могу ли я сделать что-нибудь с этим?

Ответы [ 4 ]

2 голосов
/ 07 апреля 2009

Поскольку вы уже решили свою проблему, я просто отмечу, что это будет быстрее, если вы используете rtb.AppendText (вместо Text += ...) и используете pinvoke для прокрутки вниз:

private const int WM_VSCROLL = 0x115;
private const int SB_BOTTOM = 7;

[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam,
IntPtr lParam);

// ...
// Scroll to the bottom, but don't move the caret position.
SendMessage(rtb.Handle, WM_VSCROLL, (IntPtr) SB_BOTTOM, IntPtr.Zero);
1 голос
/ 07 апреля 2009

Возможно, вы захотите попробовать

richTextBox1.BeginInvoke() 

вместо

richTextBox1.Invoke()

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

0 голосов
/ 05 мая 2015

Это старый пост, но, возможно, кто-то все еще ищет его, как я.

Вы также можете сделать, например, «for (writeToTextbox% 10 == 0)», а затем вызвать. В этом случае он будет обновляться только каждые 10 раз.

ОБНОВЛЕНИЕ: извините за опечатки! (wirte -> write) и спасибо за "HaveNoDisplayName", чтобы показать это мне!

0 голосов
/ 07 апреля 2009

Попробуйте приостановить и возобновить макет richTextBox1

    void updateoutput(string text)
    {
        try
        {
            richTextBox1.SuspendLayout();

            int len = text.Length;
            int start = richTextBox1.Text.Length;
            richTextBox1.Text += text + Environment.NewLine;
            richTextBox1.Select(start, len);
            richTextBox1.SelectionColor = Color.White;
            richTextBox1.Select(richTextBox1.Text.Length, 0);
            richTextBox1.ScrollToCaret();
        }
        finally
        {
            richTextBox1.ResumeLayout();
        }
    }

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

Я думаю, вы должны использовать Debug.Print, чтобы увидеть, что происходит вместо этого.

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