C# Winform GDI大量数据(几万个数据)绘图刷新问题

问题描述

做一个项目,使用C#GDI画图,以达到可视化目的,使用自定义的控件,整个控件通过CreateGraphics()来绘图,数据存放在DataTable有几万行的数据,需要用多列(有十几列,根据不同需要来决定使用不同的列绘图)来绘图,使用GDI如下:publicvoidPaintGraph(RectangledrawRectangle){lock(refresh_lock){BufferedGraphicsContextcurrentContext=BufferedGraphicsManager.Current;BufferedGraphicsmyBuffer=currentContext.Allocate(this.CreateGraphics(),drawRectangle);Graphicsg=myBuffer.Graphics;//绘制边框和座标轴图像DrawBackGround(g);//画线条DrawSeries(g);//画十字线if(showCrossHair){DrawCrossHair(g);}myBuffer.Render();myBuffer.Dispose();}}

在DrawSeries(g)时如下(Data是PointF(,)类型),由于会经常会使用方向向上进行放大,向下进行缩小;使用方向键向左或向右快速查看上一行或下一行的数据的一些信息(绘制在旁边)。每次放大或缩小时,座标轴需要根据当前的数据识别最大值和最小值,然后将每个数据重新计算出新的座标,再画图;每次向左或向右时,若有出现新的数据,也需要根据当前的数据识别最大值和最小值,然后将每个数据重新计算出新的座标,再画图;for(intlsJ=0;lsJ<LineSeriesList.Count;lsJ++){LineSeriesls=LineSeriesList[lsJ];for(inti=0;i<ls.Data.Count()-1;i++){g.DrawLine(ls.LinePen,ls.Data[i],ls.Data[i+1]);}}

问题是,使用方向键连续地放大、缩小,或者连续地向左或向右的时候,刷新会很卡,有时方向键停下来,控件还会延时3-5秒左右才显示完,有什么方法可以提示效率吗?

解决方案

解决方案二:
进行抽样,或者找出画图的数据范围,只画一部分。如果数据是连续的,在抽样的时候还可以取个均值
解决方案三:
你不可能把几万个数据都都画在屏幕上,即使画上了,字迹也会小的看不清(没有实用价值)所以你实际只去了一小部分数据进行展示,因此说原始数据有多么多么多是没有意义的我不知道你那些自定义方法内部是怎么做的仅就方向键控制放大缩小而言,应该是将图元绘制在GraphicsPath中,通过仿射矩阵(Matrix)完成的
解决方案四:
引用1楼johnliuyuan的回复:

进行抽样,或者找出画图的数据范围,只画一部分。如果数据是连续的,在抽样的时候还可以取个均值

因是数据分析,希望看到实际的数据变化情况,进行抽样是个不错的方向,也有试用,基本上把3万条数据抽样成4000左右(图形看起来不会失真太严重),如果条线少还好,有时同一个界面,可能会存在10几条折线(对比不同系列,及不同指标),还是没办法解决这个问题。
解决方案五:
引用2楼xuzuning的回复:

你不可能把几万个数据都都画在屏幕上,即使画上了,字迹也会小的看不清(没有实用价值)所以你实际只去了一小部分数据进行展示,因此说原始数据有多么多么多是没有意义的我不知道你那些自定义方法内部是怎么做的仅就方向键控制放大缩小而言,应该是将图元绘制在GraphicsPath中,通过仿射矩阵(Matrix)完成的

使用GraphicsPath,在放大和缩小时,因要重新计算所有的GraphicsPath,效率变差了;在向左和向右移,只要不需重新计算GraphicsPath,效率确实提高很多,在一般的移动十字线不会有延时感。Matrix的问题正在学习,因是放大或缩小,所有的像素位置都要重新计算,而且数据区间会不一样,感觉Matrix不一定能用得上,今天先试试。谢谢。
解决方案六:
现在的计算机的性能远没有这么高。满屏幕1440*960想全部填充文字都反应不过的。但还有一群程序员,写的代码随意的浪费服务器资源。你这个只有想折中的方法了,不全部显示。或者平滑过度之类的。
解决方案七:
1.绘图用控件的OnPaint或者Paint事件,不要自己创建画布,频繁的创建,影响效率2.考虑使用图片,预生成,或者缓存部分绘图3.抽样或者曲线拟合,对数据进行预处理或者干脆用控件算了,比如TeeChart
解决方案八:
引用6楼assky124的回复:

1.绘图用控件的OnPaint或者Paint事件,不要自己创建画布,频繁的创建,影响效率2.考虑使用图片,预生成,或者缓存部分绘图3.抽样或者曲线拟合,对数据进行预处理或者干脆用控件算了,比如TeeChart

显示内容只能自定义,因为会有太多细节需要自己来定义。现在的问题是放大和缩小时,区间不固定,没办法使用预生成。
解决方案九:
谁还有什么好的建议吗?
解决方案十:
假设点击一次放大或缩小需要耗费1s进行绘制如果你连续点击4次,可能需要4s进行绘制但此时前3次绘制是没有意义的,只需要1s做最后一次的绘制这个细节你考虑了没?(从你所说的“方向键连续地放大、缩小,或者连续地向左或向右的时候,刷新会很卡”,推测可能没有考虑)
解决方案十一:
引用9楼wzn721721的回复:

假设点击一次放大或缩小需要耗费1s进行绘制如果你连续点击4次,可能需要4s进行绘制但此时前3次绘制是没有意义的,只需要1s做最后一次的绘制这个细节你考虑了没?(从你所说的“方向键连续地放大、缩小,或者连续地向左或向右的时候,刷新会很卡”,推测可能没有考虑)

怎么去判断和提前中断呢?
解决方案十二:
使用独立的线程去绘制每次要绘制时判断绘制线程是否执行完毕若未完毕直接终止线程重新绘制
解决方案十三:
引用11楼wzn721721的回复:

使用独立的线程去绘制每次要绘制时判断绘制线程是否执行完毕若未完毕直接终止线程重新绘制

可以试下,谢谢。
解决方案十四:
1.自己的usercontrol在构造函数里加上双缓冲-true;2.drawline当然慢了,要drawLines,类似polyline,首先就会快几倍。3.所有的绘制代码都应该放在onpaint里,其他事件里只是调用invalidate;4.裁剪clip:只绘制无效区内部的部分。滚动的时候每次都是增加一点点无效区而已。采用1、2、3点后,你的绘图效果应该就可以接受了。采用4点后就基本不会有任何问题了。多线程、拟合之类的绘几十万上百万点的时候再考虑就行了。这么点数据真不需要多线程(当然有也更好)。
解决方案十五:
引用13楼wk_knife的回复:

1.自己的usercontrol在构造函数里加上双缓冲-true;2.drawline当然慢了,要drawLines,类似polyline,首先就会快几倍。3.所有的绘制代码都应该放在onpaint里,其他事件里只是调用invalidate;4.裁剪clip:只绘制无效区内部的部分。滚动的时候每次都是增加一点点无效区而已。采用1、2、3点后,你的绘图效果应该就可以接受了。采用4点后就基本不会有任何问题了。多线程、拟合之类的绘几十万上百万点的时候再考虑就行了。这么点数据真不需要多线程(当然有也更好)。

谢谢。

时间: 2024-10-23 04:08:11

C# Winform GDI大量数据(几万个数据)绘图刷新问题的相关文章

大数据-关于c#winform无数据库处理6万数据量的困惑

问题描述 关于c#winform无数据库处理6万数据量的困惑 有一个需求,6万条的txt文本中有八列,第一列为id其余为介绍列,id列需要检测是否重复,系统提供用户导出重复内容,提供删除重复项功能.要求减少其他第三方软件的安装,包括数据库.经过几次尝试,数据操作时间很长经常卡死.增加access数据库依然如此.请高手指点. 解决方案 你可以在循环中插入Application.DoEvents(); 这样就不会卡死了. 也可以放在工作线程中. 解决方案二: 6万记录不是很多,现在机器内存可以处理,

Js表格万条数据瞬间加载实现代码

 一条数据创建一行,如果数量大的时候,一次性要加载完数据的话,浏览器就会卡上半天,下面有个不错的方法,大家可以参考下 Js表格,万条数据瞬间加载    在Ajax动态加载数据的实际应用中,大家都习惯了一种思维方式:一条数据创建一行.  于是如果数量大的时候,一次性要加载完数据的话,浏览器就会卡上半天    受Flex的DataGrid控件的启发,在Flex的DataGrid控件中,展示数据的方法并不是有多少条数据就创建多少行,它最多只创建你在界面上所看到的十几二十行(假设为n行),如果数据多的话

mysql 查询慢-mysql 近5万条数据的表 使用联表查询 出现服务器CPU占用过多

问题描述 mysql 近5万条数据的表 使用联表查询 出现服务器CPU占用过多 mysql 近5万条数据的表 使用联表查询 出现服务器CPU占用过多,贴大神代码求优化指点!!!!!有两张表分别为:lu_yccdd 和 lu_taizhang使用的联表查询代码:SELECT distinct(t.sc_time) sc_timecount(distinct(y.id)) totalcount(distinct(t.cdd_id)) tjjg(count(distinct(y.id))-count(

oracle数据库中怎么一次性插入10万条数据

问题描述 oracle数据库中怎么一次性插入10万条数据 oracle数据库中怎么一次性插入10万条数据?急用!!!1 解决方案 最快的方法是用imp进行导入 或者用sql执行也可以(insert into )

大数据-2000万条开房数据,如何快速查询(数据库优化)

问题描述 2000万条开房数据,如何快速查询(数据库优化) 某酒店泄漏 2000 万条数据.http://kfxx.info/ 如何快速查询某个姓名的全部记录. 姓名不是唯一的,有可能重名. csv 格式数据大概 3G 大小,如果导入数据库中,大概1.5G(MySQL),而且 2000万也不是个小数目. 解决方案 索引啊,这还有什么好想的,如果你知道表结构的话,如果没有导数据库,放在linux上用cat | grep也可以 如果你舍得花时间,你可以把数据整个重构一遍,按照姓名或者其他的查询字段做

平台终端吞吐量每秒达到2万设备,每秒插入2万条数据技术方案

问题描述 平台终端吞吐量每秒达到2万设备,每秒插入2万条数据技术方案 5C 目前由于平台要处理2万设备,每秒能处理2万条数据,之前使用ActiveMQ,不能达到需求了,之前测试rabbitMQ,Redis 之类,在测试机子上面都不能达到需求,本地测试 模拟1000个线程并发处理,一个线程处理1000插入数据,始终未能达到!不知道大家有没什么好的解决方案能达到这种需求的? 解决方案 单机很难达到这样的吞吐量,需要使用负载平衡了. 解决方案二: 同多台机器分布式处理吧. 解决方案三: hadoop等

100万条数据存入mongo,通过java代码实现,要求时间在5秒之内,或者越快越好

问题描述 100万条数据存入mongo,通过java代码实现,要求时间在5秒之内,或者越快越好 通过java代码将oracle中的100万条数据查询出来,然后直接插入mongo数据库中,要求时间越短越好.我从oracle中将100万条数据查询出来花费了3秒左右.希望存入mongo的时间在5秒以内.请问各位大神有没有好的办法,谢谢. 解决方案 你可以买一个性能好一些的电脑,这样会比较快的. 解决方案二: 你把oracle查询到的数据分下类,优化时间在2秒内,存到Mongo可能会快点,最近公司也是遇

c++ 大数据 hash_map-hash_map,unordered_map以string作为键,插入一千多万条数据后崩溃

问题描述 hash_map,unordered_map以string作为键,插入一千多万条数据后崩溃 代码: #include "stdafx.h" #include"iostream" #include #include #include #include #include using namespace std; typedef hash_map myMap; void CharsAllSequen(myMap &resultMap, string &a

mysql 插入10万条数据 优化效率

问题描述 mysql 插入10万条数据 优化效率 public int addTypes(List<taobaoBean> babyList) { String sql = "insert into type (typeid,url) values (?,?) "; Connection conn = dbhelper.getConnection(driver,url,username,upwd); int result = 0; PreparedStatement stm