ロボットを制御するアプリケーションを書いています。ポートを開閉するボタンクリックメソッドがあります。
private void cONNECTToolStripMenuItem_CheckStateChanged(
object sender, EventArgs e)
{
if (cONNECTToolStripMenuItem.Checked)
{
cONNECTToolStripMenuItem.Text = "DISCONNECT!";
ports.connect();
}
else
{
cONNECTToolStripMenuItem.Text = "CONNECT!";
ports.disconnect();
}
}
さらに、シリアルポートからのデータが受信された後に呼び出される DataReceived イベントハンドラーがあります。
private void serialPort_DataReceived(
object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string data = sp.ReadExisting();
mainForm.addData(data);
}
このイベント ハンドラーが addData(data) 関数を呼び出そうとしたとき
public void addData(string data)
{
//if (!this.Disposing || !this.IsDisposed ||
// !this.listBox1.Disposing || !this.listBox1.IsDisposed)
if (this.listBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(addData);
this.Invoke(d, new object[] { data });
}
else
listBox1.Items.Add(data);
}
クロススレッド エラーが発生したため、関数の内容を InvokeRequired 条件にラップしました。
1. ports.disconnect() 関数を呼び出そうとするとプログラムがクラッシュする
public void disconnect()
{
serialPort.Close();
}
ポート クラス:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;
namespace server_client
{
public class COM_Port
{
private Main_Form mainForm;
public SerialPort serialPort;
//MySQL - 1, XML File - 2, None - 0
public int writeStatus;
public COM_Port(Main_Form form)
{
mainForm = form;
//by default niekur neirasineja nebent pasirenka
writeStatus = 0;
//sukuriam serialPort kintamaji
serialPort = new SerialPort();
//nustatom duomenis portui
serialPort.BaudRate = 9600;
serialPort.DataBits = 8;
serialPort.StopBits = StopBits.One;
serialPort.ReadTimeout = 500;
serialPort.WriteTimeout = 500;
}
~COM_Port()
{
disconnect();
serialPort.Dispose();
}
public void connect()
{
if (!serialPort.IsOpen)
if (serialPort.PortName != "")
serialPort.Open();
else
MessageBox.Show("Please choose COM Port in settings.");
}
public void disconnect()
{
//serialPort.DiscardInBuffer();
//serialPort.DiscardOutBuffer();
serialPort.Close();
}
public void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string data = null;
SerialPort sp = (SerialPort)sender;
if (sp.IsOpen)
data = sp.ReadExisting();
else
data = null;
//perduoda duomenis atvaizdavimui i maina
if (data != null)
{
mainForm.addData(data);
switch (writeStatus)
{
//neirasyti
case 0:
break;
//irasyti i mysql
case 1:
MySQL mysql = new MySQL();
break;
//irasyti i xml file
case 2:
File file = new File();
break;
default:
break;
}
}
}
}
}
ポートを閉じた後も、ロボットはまだデータを送信しており、DataReceived イベント ハンドラはシリアル ポートのバッファからそのデータを取得しようとしています。
あなたの助けのために、このラブレターを読んでくれてありがとう:)。