如何在c#应用程序的主要形式上更新列表
本文关键字:形式上 更新 列表 应用程序 | 更新日期: 2023-09-27 18:15:54
我有一个c#应用程序,它有一个名为MainView的类,用于主表单,其中包含对Connection类实例的引用。Connection类有一个SerialPort对象,这意味着我在Connection类中有一个名为dataReceivedHandler()的方法,该方法在每次接收数据时运行。
我想将此接收到的数据添加到MainView表单上的列表中,但是我不能在dataReceivedHandler()方法中这样做,因为我得到了一个交叉线程错误。
在c#中克服这个问题的最好方法是什么?我需要在MainView类中创建一个委托吗?我不确定这应该如何组织。 编辑:注意:代码已被修改,以反映我的最终解决方案。
连接类:
public class Connection{
// delegate and event for updating the datacollection in parent class
public delegate void UpdateDataCollectionDelegate(Datum newDatum);
public event UpdateDataCollectionDelegate UpdateDataCollectionEvent;
// method is called everytime the SerialPort.DataReceived event occurs
// and runs in a separate thread.
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = "";
try
{
indata = sp.ReadLine();
}
catch (TimeoutException)
{
MessageBox.Show("Data read timed out.");
}
MessageBox.Show(indata, "Raw Input");
// convert raw bytes to comma delimited string
String delimitedData = Data.RawData.convertRawToString(indata.ToCharArray());
//print delimited data to messagebox
MessageBox.Show("Received Data: 'n" + delimitedData);
// store the data in an object that represents a single result
Data.Datum newDatum = new Data.Datum(delimitedData);
UpdateDataCollectionEvent(newDatum);
}
}
MainView类:
public partial class MainView : Form{
private Connection serialCon;
// I want to update this list from the serialCon object
private BindingList<Datum> dataCollection;
public MainView(){
serialCon = new Connection();
// Point the serial connections update data collection event to the update data collection method in this class.
serialCon.UpdateDataCollectionEvent += updateDataCollection;
}
private void updateDataCollection(Datum newDatum) {
Action<Datum> del = addToDataCollection;
this.BeginInvoke(del, newDatum);
}
private void addToDataCollection(Datum newDatum) {
dataCollection.Add(newDatum);
}
}
事实上,串行端口将拥有自己的线程,当您尝试更新UI时,您将获得CrossThreadException
。
看一看这个link
,了解更多关于如何使线程安全调用windows窗体控件。
您可以通过尝试以下代码来简单地避免这种情况:
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
Action<Datum> del = UpdateMyCollection;
this.BeginInvoke(del,Data.Datum);
}
void UpdateMyCollection(Datum newDatum)
{
_dataCollection.Add(newDatum);
}