1

我已经编写了 ac# 应用程序来运行外部程序,并且我已经将它的输出重定向到我的表单中的富文本框。我使用以下设置创建了流程

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

并在 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();
}

现在问题是虽然它正在工作,但是如果应用程序的输出很大,我包含文本框的主表单会挂起。我认为每次调用调用都会导致重新绘制表单,这种情况经常发生。是否有任何替代方法可以让我看到文本框的更新,并保持表单完全激活?


更新:

我想我得到了答案,我BeginInvoke在应该使用的时候使用了Invoke.


更新1:

我尝试了 BeginInvoke 和 Suspendlayout 但它没有给我所需的功能,发生的情况是该过程已将所有标准输出恢复到字符串,但负责更新文本的线程正在花费自己的时间来打印数据. 我可以对它做点什么吗?

4

4 回答 4

2

既然你已经解决了你的问题,我会注意到如果你使用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);
于 2009-04-07T15:27:58.783 回答
1

你可能想试试

richTextBox1.BeginInvoke() 

而不是

richTextBox1.Invoke()

这至少会使调用异步。仍然不确定这是否会导致 UI 线程在绘制更新时锁定。

于 2009-04-07T15:39:28.757 回答
0

尝试暂停和恢复布局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 来查看正在发生的事情。

于 2009-04-07T16:19:23.557 回答
0

这是一个旧帖子,但也许有人还在像我一样寻找它。

您也可以这样做,例如“for(writeToTextbox % 10 == 0)”然后调用。在这种情况下,它将仅每 10 次更新一次。

更新:抱歉拼写错误!(写->写)并感谢“HaveNoDisplayName”向我展示!

于 2015-05-05T14:51:55.067 回答