前言
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的时候加锁。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论