Diskuze: c# form - příjem dat po sériové lince
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Člen
Zobrazeno 11 zpráv z 11.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Jj přečetl že neobsahuje
definici pro BeginInvoke...
Používám tyto:
using System;
using System.IO.Ports;
using System.Net.Sockets;
using System.Windows.Forms;
Nevím kde je BeginInvoke....
Zatím jsem to nikdy nepotřeboval a ani nepoužil (zatím mi vždycky stačil BackgroundWorker), ale podle mě se BeginInvoke používá pro práci s vlákny...
Aha já jsem právě našel tuto část kódu na netu... Takže právě pořádně nevím jak to funguje a chtěl jsem vysvětlení proč to nejde a jak to funguje
no je zajimave ze me ten tvuj kod jde prelozit bez problemu
není to zrovna nejlepší řešení, co sis našel - jsou tam nesmyslné a
zbytečné věci - můžeš sem dát celou třídu ?
A taky napiš, k čemu konkrétně chceš SerialPort používat - s čím a jak
často budeš komunikovat.
Tak to je zajímavé, že tobě to funguje. Nakonec jsem to vyřešil jinak
Tak jak jsem psal výše vyřešil jsem to jinak. Serial port chci využívat na zápis a vyčítání dat. Takže trvalá komunikace. Jde o komunikaci s multimetrem (nastavení měřících rozsahů, vyčtení změřené hodnoty, atd.). Tady je celá třída Communication:
using System;
using System.IO.Ports;
using System.Net.Sockets;
using System.Windows.Forms;
namespace Sender_RS232
{
/// <summary>
/// Description of Communication.
/// </summary>
public class Communication
{
private RichTextBox _displayWindow;
public SerialPort comPort = new SerialPort();
public RichTextBox DisplayWindow
{
get { return _displayWindow; }
set { _displayWindow = value; }
}
// Konstruktor tridy
public Communication()
{
_displayWindow = null;
// prida udalost, ktera je vyvolana pokud dojde k zapisu do prijimaciho stringu
comPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived);
}
public void Connected()
{
try
{
comPort.Open(); // Otevru seriovou linku
}
catch (Exception err)
{
MessageBox.Show("Port nelze otevřít" + err, MainForm.appName, MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string data = comPort.ReadExisting();
DisplayData(data);
}
private void DisplayData(string data)
{
_displayWindow.Invoke(new EventHandler(delegate
{
_displayWindow.SelectedText = string.Empty;
_displayWindow.AppendText(data + "\n");
}));
}
}
}
Po stisku tlačítka ve tříde MainForm nastavím parametry linky (rychlost,
název portu. atd.) a zavolám Connected() a otevřu port.
Teď již ve stringu data mám přimutý řetězec, ale vyskytl se mi nový
problém Potřeboval bych v
metodě DisplayData(string data) zapsat data do richTextBox1, který je
umístěn ve třídě MainForm. Nebo lépe předat data (řetězec) do MainForm
a zde zapsat do richTextBox1. Zatím jsem to zkusil takto (viz. kod), ale
nefunguje to hlásí při debagovani chybu:
NullReferenceException was unhandled
Odkaz na objekt není nastaven na instanci objektu.
Díky za rady....
Potřeboval jsem vědět, na co to používáš, abych se ujistil, že to je
opravdu nějaká jednoduchá komunikace s nějakým zařízením.
V tvém případě ,a stejně jako v 90% jiných případů se můžeš
vyfláknout na nějaké Invoke a BeginInvoke - prostě je naprosto zbytečné
zpracovávat příjem dat v jiném vlákně.
To má smysl, pokud načítáš nějaké kB/MB dat a trvá to dlouho, takže by
to blokovalo hlavní vlákno a počítám, že ten tvůj multimetr neposílá
nepřetržitý proud dat, ale pouze na vyžádání, nebo v určitých
časových intervalech.
Jinak to máš celé nějak zamotané - proč ta vlastnost
public RichTextBox DisplayWindow
{
get { return _displayWindow; }
set { _displayWindow = value; }
}
?
trochu jsem si dovolil upravit tvoji třídu
public class Communication
{
private RichTextBox _displayWindow;
public SerialPort comPort = new SerialPort();
// Konstruktor tridy
public Communication(RichTextBox _displayWindow)
{
//předáváš odkaz na již existující RTB, který jistě máš v hlavním Formu
this._displayWindow = _displayWindow;
// prida udalost, ktera je vyvolana pokud dojde k zapisu do prijimaciho stringu
comPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived);
}
public void Connected()
{
try
{
comPort.Open(); // Otevru seriovou linku
}
catch (Exception err)
{
MessageBox.Show("Port nelze otevřít" + err, MainForm.appName, MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string data = comPort.ReadExisting();
DisplayData(data);
}
private void DisplayData(string data)
{
_displayWindow.SelectedText = string.Empty;
_displayWindow.AppendText(data + "\n");
}
}
}
a ještě se zeptám - ne že by to něčemu vadilo, ale k čemu to
_displayWindow.SelectedText = string.Empty;
?
Tak jsem to podle tvých rad předělal do jednoho vlákna (do hlavního formuláře). A program už funguje. Díky za pomoc a rady....
Zobrazeno 11 zpráv z 11.