步骤:
1、选择文件夹,读取文件夹。
2、通过线程遍历文件以及解析csv文件,将csv的一行行数据保存到Queue 队列。
csv文件数据模式:0.1668056,-0.569,-0.598
3、异步委托调用队列中的数据
后台解析与UI界面不干扰,这样就解决了数据太多页面卡死的问题了,不影响用户使用。
队列真的很神奇,再也不怕重复数据的读取,定位啥的,用一个少一个......
4、绘制曲线,自动累计,动态画图
使用zedGraph控件,比vs自带控件chart功能强大,需要自行下载 zedGraph.dll 文件,拖拽至工具箱即可
5、展示DataGridView行号
灵感来源:使用多线程加载多个Xml文件到TreeView控件
例子:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.Collections; 10 using System.IO; 11 using System.Threading; 12 using ZedGraph; 13 14 namespace ThreadsOpenCsvFilesTwo 15 { 16 public partial class Form1 : Form 17 { 18 private Thread QueueFileThread;//定义一个线程,用来监视读取的文件队列 19 private delegate void csvDelegate(string instr); 20 private Queue QueueFile = new Queue();//放置要加载的数据,数据模式:0.1668056,-0.569,-0.598 21 22 public Form1() 23 { 24 InitializeComponent(); 25 26 } 27 28 /// <summary> 29 /// 委托的实现方法 30 /// </summary> 31 /// <param name="strLine"></param> 32 private void csvDel(string strLine) 33 { 34 string[] aryLine = strLine.Split(','); 35 dataGridView1.Rows.Add(aryLine); 36 dataGridView1.Refresh(); 37 } 38 39 /// <summary> 40 /// QueueFileThread 线程调用的方法 41 /// </summary> 42 /// <param name="obj"></param> 43 private void analysis(object obj) 44 { 45 string path = obj.ToString();// 文件 46 DirectoryInfo theFolder = new DirectoryInfo(path); 47 //遍历文件 48 foreach (FileInfo NextFile in theFolder.GetFiles()) 49 { 50 string fileName = NextFile.Name;//获取到的只是文件的名字,不是路径 51 string stype = fileName.Substring(fileName.LastIndexOf(".")); 52 if (stype == ".csv") 53 { 54 string filepPath = NextFile.FullName; 55 FileStream fs = new FileStream(filepPath, FileMode.Open); 56 StreamReader sr = new StreamReader(fs, Encoding.UTF8); 57 bool IsFirst = false;//是否读取第一行 58 string strLine = ""; 59 //逐行读取CSV中的数据 60 while ((strLine = sr.ReadLine()) != null) 61 { 62 if (IsFirst == false) 63 { 64 IsFirst = true; 65 } 66 else 67 { 68 QueueFile.Enqueue(strLine); 69 } 70 } 71 } 72 } 73 74 } 75 76 77 78 private void timer1_Tick(object sender, EventArgs e) 79 { 80 csvDelegate cd = new csvDelegate(csvDel); 81 if (QueueFile.Count > 0) 82 { 83 this.BeginInvoke(cd, QueueFile.Dequeue());// UI线程异步委托 84 85 } 86 87 this.zedGraphControl1.GraphPane.CurveList.Clear();//清空之前画的图 88 this.zedGraphControl1.GraphPane.AxisChange();// 更新 89 GraphPane myPane = this.zedGraphControl1.GraphPane; 90 this.zedGraphControl1.GraphPane.Title.Text = "折线图"; 91 myPane.XAxis.Title.Text = "Sequence";// 顺序 92 myPane.YAxis.Title.Text = "Time"; 93 myPane.Y2Axis.Title.Text = "Front, Back"; 94 myPane.Y2Axis.IsVisible = true;//显示第二个y轴 95 96 // 数据 97 List<double> column1 = new List<double>();// y 98 List<double> column2 = new List<double>();// y2 99 List<double> column3 = new List<double>();// y3 100 List<double> column4 = new List<double>();// x 101 102 for (int i = 0; i < this.dataGridView1.Rows.Count - 1; i++) 103 { 104 DataGridViewRow row = new DataGridViewRow(); 105 row = dataGridView1.Rows[i]; 106 column1.Add(double.Parse(row.Cells["Time"].Value.ToString())); 107 column2.Add(double.Parse(row.Cells["Front"].Value.ToString())); 108 column3.Add(double.Parse(row.Cells["Back"].Value.ToString())); 109 column4.Add(i + 1); 110 } 111 112 double[] y = column1.ToArray(); 113 double[] y2 = column2.ToArray(); 114 double[] y3 = column3.ToArray(); 115 double[] x = column4.ToArray(); 116 117 // Fill the axis background with a color gradient 118 myPane.Chart.Fill = new Fill(Color.FromArgb(255, 255, 245), Color.FromArgb(255, 255, 190), 90F); 119 120 // 生成曲线 121 LineItem myCurve = myPane.AddCurve("Time", x, y, Color.Blue, SymbolType.None); 122 LineItem myCurve2 = myPane.AddCurve("Front", x, y2, Color.Orange, SymbolType.None); 123 myCurve2.IsY2Axis = true; //手动改为按【Y2Axis】的刻度描画 124 LineItem myCurve3 = myPane.AddCurve("Back", x, y3, Color.Red, SymbolType.None); 125 myCurve3.IsY2Axis = true; 126 127 // 手动设置x y y2 轴的范围 128 myPane.XAxis.Scale.Min = 0; 129 myPane.YAxis.Scale.Min = 0; 130 myPane.YAxis.Scale.Max = 200; 131 myPane.Y2Axis.Scale.Min = -1; 132 myPane.Y2Axis.Scale.Max = 2; 133 134 // 显示Y轴网格线 135 myPane.YAxis.MajorGrid.IsVisible = true; 136 myPane.YAxis.MinorGrid.IsVisible = true; 137 myPane.Y2Axis.MajorGrid.IsVisible = true; 138 myPane.Y2Axis.MinorGrid.IsVisible = true; 139 140 zedGraphControl1.AxisChange(); 141 zedGraphControl1.Invalidate(); 142 } 143 144 145 private void dataGridView1_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e) 146 { 147 e.Row.HeaderCell.Value = string.Format("{0}", e.Row.Index + 1); //dataGridView显示行号 148 } 149 150 private void button1_Click_1(object sender, EventArgs e) 151 { 152 dataGridView1.Rows.Clear(); 153 FolderBrowserDialog dialog = new FolderBrowserDialog(); 154 dialog.Description = "请选择CSV所在文件夹"; 155 if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) 156 { 157 if (string.IsNullOrEmpty(dialog.SelectedPath)) 158 { 159 MessageBox.Show(this, "文件夹路径不能为空", "提示"); 160 return; 161 } 162 string path = dialog.SelectedPath; 163 textBox1.Text = path; 164 QueueFileThread = new Thread(new ParameterizedThreadStart(this.analysis)); 165 QueueFileThread.IsBackground = true;// 设置为后台线程 166 QueueFileThread.Start(path); 167 168 timer1.Start(); 169 } 170 } 171 } 172 }
展示结果: