1

我很确定只有我做错了。

Form1有一个按钮,onclick 调用我的 serialConn.cs 中的一个方法,称为connect().

public static bool connect(string comPort) {
        BTserial = new SerialPort(comPort, 9600, Parity.None, 8, StopBits.One);
        BTserial.Open();
        if (BTserial.IsOpen) {
            BTserial.DataReceived += new SerialDataReceivedEventHandler(DataReceivedEvent);
            return true;
        } else {
            return false;
        }
    }

private static void DataReceivedEvent(object sender, SerialDataReceivedEventArgs e) {
        Debug.WriteLine("Data Incomming!");
        // Check if Chars are received
        if (e.EventType == SerialData.Chars) {
            Debug.WriteLine("Chars!");
            // Create new buffer
            byte[] ReadBuffer = new byte[BTserial.BytesToRead];

            // Read bytes from buffer
            BTserial.Read(ReadBuffer, 0, ReadBuffer.Length);
            BTserial.DiscardInBuffer();

            // Encode to string
            string data = bytesToString(ReadBuffer);

            ReadBuffer = null;
            data = null;
        }
    }

这一切都很好,但是当收到数据时,我希望它打印在TextBox我的控制器中Form1。但由于我DataReceivedEvent()是一个static(我想我必须是?),我无法访问任何东西?那么解决这个问题的最佳方法是什么?

4

1 回答 1

1

您需要将 Form 实例传递给此连接方法(来自按钮的事件处理程序):

public class Form1 : Form {

  public void Button1_Click(object sender, EventArgs e) {
    serialConn.connect("the com port here", this);
  }

  // ... etc ...

}

在 serialConn 中:

public static bool connect(string comPort, Form1 whichForm) {

然后您可以使用 lambda 函数并关闭其中的“whichForm”引用,如下所示:

但此外,您应该确保您实际上没有从除主线程之外的另一个线程修改 GUI——由于 SerialPort 类的性质很可能从另一个后台线程引发事件,这很有可能——因此 this.Invoke( some other lambda ) 编组该特定操作,该操作又在主线程上执行。

MSDN 明确指出:http: //msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived.aspx

从 SerialPort 对象接收数据时,在辅助线程上引发 DataReceived 事件。由于此事件是在辅助线程而不是主线程上引发的,因此尝试修改主线程中的某些元素(例如 UI 元素)可能会引发线程异常。如果需要修改主窗体或控件中的元素,请使用 Invoke 将更改请求发回,这将在适当的线程上完成工作。

public static bool connect(string comPort, Form1 whichForm) {
    BTserial = new SerialPort(comPort, 9600, Parity.None, 8, StopBits.One);
    BTserial.Open();
    if (BTserial.IsOpen) {
        BTserial.DataReceived += (sender, e) => {
          Debug.WriteLine("Data Incomming!");
          // Check if Chars are received
          if (e.EventType == SerialData.Chars) {
              Debug.WriteLine("Chars!");
              // Create new buffer
              byte[] ReadBuffer = new byte[BTserial.BytesToRead];

              // Read bytes from buffer
              BTserial.Read(ReadBuffer, 0, ReadBuffer.Length);
              BTserial.DiscardInBuffer();

              // Encode to string
              string data = bytesToString(ReadBuffer);


              Action toBeRunOnGuiThread = () => whichForm.theTextBox.Text = data;

              // to guard yourself from all evil
              // you could check to see if it is needed to
              if (whichForm.InvokeRequired) 
                // marshal the call to the action all the way to the GUI thread
                whichForm.Invoke(toBeRunOnGuiThread);
              else
                // or, if we ARE on the GUI thread already, just call it from this thread
                toBeRunOnGuiThread();

              ReadBuffer = null;
              data = null;
          }
    };
        return true;
    } else {
        return false;
    }
}
于 2013-02-21T23:31:14.563 回答