0%

c# richtextbox更新大量数据不卡死的办法

前言

c# 的richtextbox对读入几十万行大数据或者频繁更新经常卡死界面几分钟。
终于找到一个通过子线程更新的方法,实际测试对于40万行可以在10秒内完成更新,并且运行中界面不卡死可以操作。

一、richtextbox更新方法

richtextbox更新有两种更新方法:richtextbox.appendtext() 和 richtextbox.text = richtextbox.text + str。
在子线程中可使用 richtextbox.text = richtextbox.text + str。

为了提高效率,使用了StringBuilder sb进行缓冲,每maxDisplayline行更新一次richtextbox,并根据行数增加动态调整了maxDisplayline的大小。

二、使用步骤

代码如下(核心代码):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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的时候加锁。
————————————————
版权声明:本文为CSDN博主「noworrycd」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/noworrycd/article/details/123867636