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

これは古い投稿ですが、私のようにまだ探している人がいるかもしれません。

「for(writeToTextbox % 10 == 0)」のようにして呼び出すこともできます。この場合、10 回ごとにのみ更新されます。

追記:誤字脱字すみません!(書き込み -> 書き込み) 「HaveNoDisplayName」が表示してくれてありがとう!

于 2015-05-05T14:51:55.067 に答える
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 に答える