警惕beginInvoke的性能陷阱
Control.BeginInvoke用于异步更新GUI上边的数据,通过是辅助线程得到数据之后需要更新到UI线程上边,由于和UI线程不在一个线程上运行,当需要访问UI上的控件的时候,就会抛出异常。
通常使用Control.BeginInvoke的方法是,使用的是.Net Framework提供的Fun<> 和Action<>等预定义类型。如
/// <summary> /// 接收到新数据 /// </summary> /// <param name="Data"></param> private void dtm__OnNewRow(List<string> Data) { Action<List<string>> myFun = AddNewRowToTable; this.BeginInvoke(myFun, new object[] { Data}); } private void AddNewRowToTable(List<string> data) { //do something }
这里string 是值类型,所以在调用的过程中会尝试多次的 对象-值和值-对象的封箱和拆箱操作。。引起性能瓶颈。
解决方法是使用 MethodInvoker 的匿名方法,代码如下:
/// <summary> /// 接收到新数据 /// </summary> /// <param name="Data"></param> private void dtm__OnNewRow(List<string> Data) { Action<List<string>> myFun = AddNewRowToTable; this.BeginInvoke((MethodInvoker)delegate() { Row r = new Row(); foreach (string s in Data) { r.Cells.Add(new Cell(s)); } XPtbData.TableModel.Rows.Add(r); if (dtm_.DataTableWorkingMode == SensorWorkingMode.One_Triggle_Sensor || dtm_.DataTableWorkingMode == SensorWorkingMode.Two_Triggle_Sensor) UpdateSummaryTable(); }); //this.BeginInvoke(myFun, new object[] { Data}); } private void AddNewRowToTable(List<string> data) { // do something }