c# listbox 显示大量数据速度很慢,如何解决?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c# listbox 显示大量数据速度很慢,如何解决?相关的知识,希望对你有一定的参考价值。
c#使用listbox加载10m以上数据,第一次显示的时候速度很慢要几分钟,cpu占用%100,如何解决这个问题?谢谢,不用考虑这种设计是否合理
具体是这样实现的:
form里有两个tabpage1和tabpage2,当前窗体默认给用户呈现的是tabpage1,listbox是在tabpage2中,通过items.add把所有数据都加入listbox,程序运行完毕后,用户从tabpage1切换到tabpage2,这个时候显示listbox所有内容的过程就很慢,要好几分钟,cpu占用达到100%。
不考虑分页,如何能使显示时间减少?
谢谢,10m的记录总字节,先不考虑分页(因为涉及到各个tabpage自动跳转功能),能否解决这个问题?
10m内容是直接从另一个程序的文本日志取过来的,循环add的速度用户可以接受,就是第一次显示很慢,只要第一次显示完成后,再怎么切换都很顺畅。
多谢各位,咱们先解决如何提高listbox第一次显示大量数据的效率?
private void button1_Click(object sender, EventArgs e)
DateTime dt = DateTime.Now;
string[] strArr = File.ReadAllLines("D:\\AAAA.txt", Encoding.Default);
listBox1.DataSource = strArr;
TimeSpan ts = DateTime.Now - dt;
MessageBox.Show(ts.Seconds.ToString());
参考技术B 第一 为什么不考虑是否合理 100%不合理
解决方法
1.优化数据库
2.用存储过程写
3.分批ITEM.ADD 意思就是 你可以1M 1M的加 就比较快了 参考技术C 设计的绝对的不合理。想你这样如果100M的数据,你有没有想过数据量多大?
你这样循环ADD。时间不久才怪。最好的方式就是利用算法,一次取多少。 参考技术D 10m以上数据太多了。而且用items.add这样来增加数据循环的次太多了,如果是用来显示的用datagridview速度会提高很多。 第5个回答 2009-07-03 10m是多少?
是记录数,还是记录总字节?
如果是我,我会想办法分页。
你呈现给用户10M的记录有意义么?得看到什么时候?交互性不好,不友好!
如何在显示大量文本时加快滚动响应速度
【中文标题】如何在显示大量文本时加快滚动响应速度【英文标题】:How to speed up scrolling responsiveness when displaying lots of text 【发布时间】:2016-12-09 17:25:15 【问题描述】:我正在尝试创建一个 Python 脚本来突出显示 .txt 文件中的特定模式。为此,我修改了一个使用 Tkinter 突出显示给定数据集的脚本。但是,我倾向于让它处理的文件大约是 10000 行,这导致滚动缓慢,因为我认为它渲染了所有内容 - 无论它是否在屏幕上(如果我是,请纠正我错误的)。是否可以更改我的代码,使其以更有效的方式呈现输出?我已经尝试寻找一种方法来做到这一点,但我自己没有找到任何东西。
我的代码如下:
from Tkinter import *
class FullScreenApp(object):
def __init__(self, master, **kwargs):
self.master=master
pad=3
self._geom='200x200+0+0'
master.geometry("0x1+0+0".format(
master.winfo_screenwidth()-pad, master.winfo_screenheight()-pad))
master.bind('<Escape>',self.toggle_geom)
def toggle_geom(self,event):
geom=self.master.winfo_geometry()
print(geom,self._geom)
self.master.geometry(self._geom)
self._geom=geom
root = Tk()
app = FullScreenApp(root)
t = Text(root)
t.pack()
#Import file
with open('data.txt') as f:
for line in f:
t.insert(END, line)
#Search terms - Leave blank if not required
search_term0 = '0xCAFE'
search_term1 = '0x0011'
search_term2 = '0x961E'
search_term3 = '0x0000'
search_term4 = ''
#Assigns highlighted colours for terms not blank
t.tag_config(search_term0, background='red')
if search_term1 != '':
t.tag_config(search_term1, background='red')
if search_term2 != '':
t.tag_config(search_term2, background='red')
if search_term3 != '':
t.tag_config(search_term3, background='red')
if search_term4 != '':
t.tag_config(search_term4, background='red')
#Define search
#Requires text widget, the keyword, and a tag
def search(text_widget, keyword, tag):
pos = '1.0'
while True:
idx = text_widget.search(keyword, pos, END)
if not idx:
break
pos = '+c'.format(idx, len(keyword))
text_widget.tag_add(tag, idx, pos)
#Search for terms that are not blank
search(t, search_term0, search_term0)
if search_term1 != '':
search(t, search_term1, search_term1)
if search_term2 != '':
search(t, search_term2, search_term2)
if search_term3 != '':
search(t, search_term3, search_term3)
if search_term4 != '':
search(t, search_term4, search_term3)
root.mainloop()
以下链接中给出了文件中的数据示例:here
非常感谢您的宝贵时间,非常感谢。
【问题讨论】:
我已更改问题的标题以反映您想要修复的内容,而不是您认为需要修复的内容。主要是因为我认为情况会相反:我认为渲染所有内容会在第一次显示时变得非常慢,但滚动速度非常快(因为它已经完成了所有渲染)但必须重新渲染每个它滚动的时间会减慢它的速度。 您的代码中的某些缩进被破坏了。 “按住时,它可能会减慢到每秒 2 或 3 行” - 只有您在问题中发布的 exact 代码?另外,文件中的每一行都长吗?我每秒可能会收到 40-50 行。 我怀疑你有一些操作系统设置限制了这一点 - 你可以用鼠标滚轮更快地滚动吗? 我拿了一个quick screencap 我的滚动。我开始用鼠标滚轮滚动,但后来我改为用箭头键滚动。 【参考方案1】:假设 MCVE 如下:
import tkinter as tk
def create_text(text_len):
_text = list()
for _ in range(text_len):
_text.append("\n".format(_))
_text = "".join(_text)
return _text
if __name__ == '__main__':
root = tk.Tk()
txt = tk.Text(root)
txt.text = create_text(10000)
txt.insert('end', txt.text)
txt.pack()
root.mainloop()
分析
基于this 我认为这不是渲染问题。我认为拥有fixed rate of registering <KeyPress>
events 是个问题。这意味着每秒注册的事件数量是固定的,即使硬件可能能够以更快的速度注册。类似的规则也应该适用于鼠标滚动事件。
渲染解决方案
也许为txt['height']
的缓冲区比例分割文本会有所帮助。但这不就是 Tk 应该呈现的方式吗?
渲染无关问题的解决方案
如果一个步骤将被定义为光标移动到上一行或下一行,对于每个注册的 Up 或 Down 事件;然后scrolling_speed = step * event_register_frequency
。
通过增加步长
一个简单的解决方法是为键绑定的每个注册增加步长,例如增加要跳转的行数。
但是已经有这样的默认行为,假设页面长度> 1行,Page Up或Page Down具有页面的步长。这使得滚动速度增加,即使事件注册率保持不变。
或者,可以定义一个具有更大步长的新事件处理程序,为 Up 和 Down 的每次注册调用多个光标移动,例如:
import tkinter as tk
def create_text(text_len):
_text = list()
for _ in range(text_len):
_text.append("\n".format(_))
_text = "".join(_text)
return _text
def step(event):
if txt._step_size != 1:
_no_of_lines_to_jump = txt._step_size
if event.keysym == 'Up':
_no_of_lines_to_jump *= -1
_position = root.tk.call('tk::TextUpDownLine', txt, _no_of_lines_to_jump)
root.tk.call('tk::TextSetCursor', txt, _position)
return "break"
if __name__ == '__main__':
root = tk.Tk()
txt = tk.Text(root)
txt.text = create_text(10000)
txt.insert('end', txt.text)
txt._step_size = 12
txt.bind("<Up>", step)
txt.bind("<Down>", step)
txt.pack()
root.mainloop()
通过模仿按键事件注册表率增加:
正如here 中提到的,实际上修改按键注册表速率超出了 Tk 的范围。相反,它可以被模仿:
import tkinter as tk
def create_text(text_len):
_text = list()
for _ in range(text_len):
_text.append("\n".format(_))
_text = "".join(_text)
return _text
def step_up(*event):
_position = root.tk.call('tk::TextUpDownLine', txt, -1)
root.tk.call('tk::TextSetCursor', txt, _position)
if txt._repeat_on:
root.after(txt._repeat_freq, step_up)
return "break"
def step_down(*event):
_position = root.tk.call('tk::TextUpDownLine', txt, 1)
root.tk.call('tk::TextSetCursor', txt, _position)
if txt._repeat_on:
root.after(txt._repeat_freq, step_down)
return "break"
def stop(*event):
if txt._repeat_on:
txt._repeat_on = False
root.after(txt._repeat_freq + 1, stop)
else:
txt._repeat_on = True
if __name__ == '__main__':
root = tk.Tk()
txt = tk.Text(root)
txt.text = create_text(10000)
txt.insert('end', txt.text)
txt._repeat_freq = 100
txt._repeat_on = True
txt.bind("<KeyPress-Up>", step_up)
txt.bind("<KeyRelease-Up>", stop)
txt.bind("<KeyPress-Down>", step_down)
txt.bind("<KeyRelease-Down>", stop)
txt.pack()
root.mainloop()
通过增加步长和模仿注册率增加
import tkinter as tk
def create_text(text_len):
_text = list()
for _ in range(text_len):
_text.append("\n".format(_))
_text = "".join(_text)
return _text
def step_up(*event):
_no_of_lines_to_jump = -txt._step_size
_position = root.tk.call('tk::TextUpDownLine', txt, _no_of_lines_to_jump)
root.tk.call('tk::TextSetCursor', txt, _position)
if txt._repeat_on:
root.after(txt._repeat_freq, step_up)
return "break"
def step_down(*event):
_no_of_lines_to_jump = txt._step_size
_position = root.tk.call('tk::TextUpDownLine', txt, _no_of_lines_to_jump)
root.tk.call('tk::TextSetCursor', txt, _position)
if txt._repeat_on:
root.after(txt._repeat_freq, step_down)
return "break"
def stop(*event):
if txt._repeat_on:
txt._repeat_on = False
root.after(txt._repeat_freq + 1, stop)
else:
txt._repeat_on = True
if __name__ == '__main__':
root = tk.Tk()
txt = tk.Text(root)
txt.text = create_text(10000)
txt.insert('end', txt.text)
txt._step_size = 1
txt._repeat_freq = 100
txt._repeat_on = True
txt.bind("<KeyPress-Up>", step_up)
txt.bind("<KeyRelease-Up>", stop)
txt.bind("<KeyPress-Down>", step_down)
txt.bind("<KeyRelease-Down>", stop)
txt.pack()
root.mainloop()
【讨论】:
它说我可以在 1 小时内提供赏金【参考方案2】:所以这可以通过称为多线程的东西来解决。一台计算机可以同时执行多项任务,否则您的网络体验将不一样。这是一个演示多线程的简单函数
from threading import Thread
def execOnDifferentThread(funct=print, params=("hello world",)):
t = Thread(target=funct, args=params)
t.start()
现在请注意,这可能不是最好的示例,但现在要并行运行一个函数,您所要做的就是 execOnDifferentThread(funct=A, params=B)
其中 A 是函数名称,B 是 元组 将传递给您的函数的参数。现在,我不想为您编写代码,但是使用此功能,您可以multi-thread
代码的某些部分以使其更快。如果您真的被卡住了,只需评论在哪里并提供帮助。但是请先自己尝试,现在您已经掌握了多线程的能力
【讨论】:
另外,记住在多线程中使用全局变量时,将它们声明为全局变量 我建议线程化代码的t.insert
和search
部分以上是关于c# listbox 显示大量数据速度很慢,如何解决?的主要内容,如果未能解决你的问题,请参考以下文章
c# winform listbox 如何 获取 当前 选中的值 急!!!
C#开发的winform程序,窗体打开的速度很慢,请高手指点。。谢了先。。。
MFC,ListBox使用 InsertColumn添加列,在列表框中却无论如何都不显示,很是郁闷,求解,正解追加高分。