如何在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);
    }
}

如何在c#应用程序的主要形式上更新列表

事实上,串行端口将拥有自己的线程,当您尝试更新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);
         }