前言
c# 的richtextbox对读入几十万行大数据或者频繁更新经常卡死界面几分钟。
终于找到一个通过子线程更新的方法, 实际测试对于40万行可以在10秒内完成更新, 并且运行中界面不卡死可以操作。
一、richtextbox更新方法
richtextbox更新有两种更新方法:
richtextbox.appendtext() 和 richtextbox.text = richtextbox.text + str。
在子线程中可使用 richtextbox.text = richtextbox.text + str。
为了提高效率, 使用了StringBuilder sb进行缓冲, 每maxDisplayline行更新一次richtextbox, 并根据行数增加动态调整了maxDisplayline的大小。
二、使用步骤
代码如下(核心代码):
maxDisplayline = 1 * 1000; // 1000行 StringBuilder sb = new StringBuilder(); Stopwatch swGlobal = new Stopwatch(); string[] sblineslist = in_str.Split(new char[] { '\n' }); // instr 为输入字符串,可以是文件读入的 // static readonly object lockSb = new object(); richTextBoxDisplay.Focus(); sb.Clear(); Thread.Sleep(1); swGlobal.Reset(); swGlobal.Start(); Thread t = new Thread((ThreadStart)delegate { try { for (int i = 0; i < sblineslist.Length; i++) { if (stopSign) { return; } // lock(lockSb) sb.Append(sblineslist[i] + "\n"); if (i > 0 && i % maxDisplayline == 0) { this.Invoke((EventHandler)delegate { labelStatus.Text = "状态: " + count + "/" + manualSyncFilesFullname.Count + " " + runsecond + "s -> " + (i + 1) + " Act/Rest: " + swGlobal.ElapsedMilliseconds/1000 + "/" + (int)(1.0 * swGlobal.ElapsedMilliseconds * (sblineslist.Length - (i+1)) /(i+1) /1000) + "s"; labelStatus.Update(); }); if (sb.Length > 0) { // lock(lockSb) this.richTextBoxDisplay.Text = this.richTextBoxDisplay.Text + sb.ToString(); sb.Clear(); } maxDisplayline = maxDisplayline * ((int)Math.Sqrt(i/ maxDisplayline)); } } if (sb.Length > 0) { // lock(lockSb) this.richTextBoxDisplay.Text = this.richTextBoxDisplay.Text + sb.ToString(); sb.Clear(); } this.Invoke((EventHandler)delegate { labelStatus.Text = "状态: " + count + "/" + manualSyncFilesFullname.Count + " " + runsecond + "s -> " + sblineslist.Length.ToString() +" Act: " + swGlobal.ElapsedMilliseconds / 1000 + "s"; labelStatus.Update(); }); } catch (Exception ex) { try { stopSign = true; this.Invoke((EventHandler)delegate { labelStatus.Text = "异常错误: " + ex.Message; labelStatus.Update(); }); } catch { } } }); t.IsBackground = true; t.Start(); Thread.Sleep(33); while (!stopSign && t != null && t.IsAlive) { Application.DoEvents(); Thread.Sleep(3); }
总结
richtextbox.text 支持在子线程中直接操作和访问。
如果需要多线程并发交互更新,需要在操作sb的时候加锁。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。