使.NET TextBox工作FIFO样式

Edg*_*tat 3 .net c# user-interface textbox

我有一个用C#编写的win GUI应用程序,其中有一个TextBox我写日志的组件.在某些时候,它太过负载,整个应用程序开始动摇.我想建立一个有效的机制,使其成为一个FIFO,意思是 - 使其固定大小并自动删除最旧的内容.

这样做有什么.net/c#功能吗?否则,这样做的正确方法是什么?

更新:我还有其他类型的文本数据,而不仅仅是日志.因此,ListBox对我来说,这不是一个合适的解决方案.

Sea*_*sey 6

虽然我确信有更好的解决方案 - 当我认为FIFO时 - 我认为Queue.因此,您可以执行类似于创建字符串队列以添加日志项并设置整数以表示最大日志项数的操作.

private Queue<string> logQueue = new Queue<string>();
private const int logMax = 100;
Run Code Online (Sandbox Code Playgroud)

那么你可以像这样设置一个日志记录方法.

public void Log(string logText)
{
    // this should only ever run for 1 loop as you should never go over logMax
    // but if you accidentally manually added to the logQueue - then this would
    // re-adjust you back down to the desired number of log items.
    while (logQueue.Count > logMax - 1)
        logQueue.Dequeue();

    logQueue.Enqueue(logText);
    textBox.Text = string.Join(Environment.NewLine, logQueue.ToArray());
}
Run Code Online (Sandbox Code Playgroud)

这应该可以为您提供所需的功能.

这种方法的一个明显缺点是你将文本存储在内存中两次.一旦进入队列,一次作为文本框中的连接字符串.如果这不是一个大问题 - 那么这可能会奏效.


Ben*_*igt 5

要为文本创建循环缓冲区,我将使用a StringBuilder,其容量设置为我想要显示的数据量的大约两倍.

const int DisplaySize = 10000;
StringBuilder fifo = new StringBuilder(2 * DisplaySize);

string AppendToFifo( string s )
{
    if (s.Length >= DisplaySize) {
        // FACT: the display will only include data from s
        // therefore, toss the entire buffer, and only keep the tail of s
        fifo.Clear();
        fifo.Append(s, s.Length - DisplaySize, DisplaySize);
        return fifo.ToString();
    }
    if (fifo.Length + s.Length > fifo.Capacity) {
        // FACT: we will overflow the fifo
        // therefore, keep only data in the fifo that remains on the display
        fifo.Remove(0, fifo.Length + s.Length - DisplaySize);
    }
    fifo.Append(s);
    if (fifo.Length <= DisplaySize) {
        // FACT: the entire fifo content fits on the display
        // therefore, send it all
        return fifo.ToString();
    }
    // FACT: the fifo content exceed the display size
    // therefore, extract just the tail
    return fifo.ToString(fifo.Length - DisplaySize, DisplaySize);
}
Run Code Online (Sandbox Code Playgroud)

当没有if条件为真时,快速路径避免了所有不必要的副本(在.NET世界中,字符串是不可变的,无法避免创建输出字符串的最终副本).而在其他情况下,只复制所需的字符.增加缓冲区的容量将提高快速路径的利用率.我一直小心翼翼地避免做的是创建一个字符串对象,其中旧内容保留在显示器上,除了与新内容连接外没有任何意义,并立即变成垃圾.

显然,如果你使用p/invoke传递一个指向StringBuffer内容的指针而不是复制出一个子字符串,那将更有效.