在Forms应用程序中,我正在显示生成大量输出的长时间运行的命令行应用程序的日志输出.我在后台启动程序,捕获其输出,并使用AppendText将其显示在TextBox中.我更喜欢只显示例如最后1000行.从TextBox中删除行是很昂贵的,而TextBox实际上并不是滚动日志显示的最佳方法.
关于在Windows窗体中执行滚动日志窗口的最佳控件的任何想法?
我以前有列表框做这种事情.如果行数达到1000,您只需删除第一行.如果日志行太长,您可以使列表框更宽一些(取决于日志信息以及是否可以从第一个可见的捕获含义)没有水平滚动的单词)并使水平滚动条可见.
正是我需要的.我用下面的代码解决了这个问题,它保留了最后添加的项目:
delegate void UpdateCCNetWindowDelegate(String msg); private void Message2CCNetOutput(String message) { // Check whether the caller must call an invoke method when making method calls to listBoxCCNetOutput because the caller is // on a different thread than the one the listBoxCCNetOutput control was created on. if (listBoxCCNetOutput.InvokeRequired) { UpdateCCNetWindowDelegate update = new UpdateCCNetWindowDelegate(Message2CCNetOutput); listBoxCCNetOutput.Invoke(update, message); } else { listBoxCCNetOutput.Items.Add(message); if (listBoxCCNetOutput.Items.Count > Program.MaxCCNetOutputLines) { listBoxCCNetOutput.Items.RemoveAt(0); // remove first line } // Make sure the last item is made visible listBoxCCNetOutput.SelectedIndex = listBoxCCNetOutput.Items.Count - 1; listBoxCCNetOutput.ClearSelected(); } }
有同样的需求,并赞赏了很多这方面的帮助.这是一个略微修改的版本.
创建一个列表框:
在主线程中(在代码的初始部分),将其存储为存储对UI线程的引用:
Thread m_UIThread; .... m_UIThread = Thread.CurrentThread;
那么这是你的日志方法,可以从任何线程调用:
public void AddToLog(String message) { if (Thread.CurrentThread != m_UIThread) { // Need for invoke if called from a different thread this.Dispatcher.BeginInvoke( DispatcherPriority.Normal, (ThreadStart)delegate() { AddToLog(message); }); } else { // add this line at the top of the log lbLog.Items.Insert(0, message); // keep only a few lines in the log while (lbLog.Items.Count > LOG_MAX_LINES) { lbLog.Items.RemoveAt(lbLog.Items.Count-1); } } }