[ bigguy @ 17.01.2010. 17:06 ] @
Imam malo cudan problem. Mislim da je po sredi moje ne poznavanje rada sa nitima i njihovo koriscenje, pa sam se zato obratio za pomoc. O ovoj aplikaciji nesto sam ranije vec postavljao pitanje, ali ipak cu ponoviti ukratko sta radim. Rec je o sledecem: radim jednu aplikaciju vezanu za prijem i slanje podataka putem SerialPort-a. Sve ono sto pristize i salje se sa porta treba da bude vidljivo, odnosno da se ispisuje u okviru jednog RichTextBox-a. Takodje, kad god se neki podatak posalje preko porta to korisnik moze vizualno da vidi, osim ispisivanja teksta u okviru RichTexBox-a, i na osnovu promene male ikonice iz crvene boje u zelenu. Simuliram posojanje neke vrste diodice i to traje 1/3 sekunde. Postoje dve ikonice pbTX za slanje podataka i pbRX za prijem podataka. Njih sam postavio kao Timer-e koji se ukljucuju prilikom pokretanja funkcije za slanje podataka timerTX i prilikom prijema podataka timerRX. Ovi timer-i imaju event timer_Tick. Radi po meni lakseg organizovanja odvojio sam GUI korisnika od class PortProperties gde se nalaze i podesavaju osnovni parametri port-a, a slanje i prijem funkcije zbog svoje slozenosti odvojio sam u posebne klase class Send i class Received. Ove klase pozivam iz class PortProperties putem funkcija. Ceo program testiram preko virtualnog COM3 porta, to jest preko istog porta se i primaju i salju podaci. Problem mi se javio upravo u ovim segmentima. Dacu najpre ukratko skraceni kod, a potom cu objasniti i problem: Code: public partial class Form1 : Form { public Form1() { InitializeComponent(); } PortProperties portProperties = new PortProperties(); private void Form1_Load(object sender, EventArgs e) { frmForm1 = this; LoadValues(); SetDefaults(); SetControlState(); } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { portProperties.ClosePort(); } private void SetDefaults() { ...//podesavanje osnovnih parametara } private void LoadValues() { ...//ucitavanje vrednosti parametara SerialPort-a } private void SetControlState() { pictureBox1.Image = ...//postavljanje na odgovarajucu ikonicu pictureBox2.Image = ..//postavljanje na odgovarajucu ikonicu } private void btnOpen_Click(object sender, EventArgs e) { portProperties._pbRX = pictureBox1; portProperties._pbTX = pictureBox2; portProperties._rtbDisplay = rtbDisplay; ...//ostala objekti na formi portProperties.OpenPort(); } private void btnSend_Click(object sender, EventArgs e) { string message = "Hello World!"; byte[] sendMessage = Encoding.ASCII.GetBytes(message); portProperties.SendByte(sendMessage); } } Code: class PortProperties { Send send = new Send(); Received received = new Received(); public RichTextBox _rtbDisplay { get; set; } public PictureBox _pbRX { get; set; } public PictureBox _pbTX { get; set; } ...//ostali parametri SerialPort-a i MainForm-e private SerialPort comPort = new SerialPort(); public PortProperties() { _rtbDisplay = null; _pbRX = null; _pbTX = null; ... comPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived); } public PortProperties( PictureBox pb1, PictureBox pb2, RichTextBox RTBDISPLAY,...) { _pbRX = pb1; _pbTX = pb2; _rtbDisplay = RTBDISPLAY; ... comPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived); } public bool OpenPort() { ...//postavljanje propertiza SerialPort-a RTBDisplay(true); } public bool ClosePort() { ...//zatvaranje SerialPort-a RTBDisplay(false); } private void RTBDisplay(bool state) { _rtbDisplay.Invoke(new EventHandler(delegate { ...//Ispisivanje teksta prilikom otvaranja ili zatvaranja SerialPort-a } void comPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { received._rtbDisplay = _rtbDisplay; received._pbRX = _pbRX; received.ReceivedData(comPort); } public void SendByte(byte[] msg) { send._rtbDisplay = _rtbDisplay; send._pbTX = _pbTX; send.WriteData(comPort, msg); } } Code: class Send { private delegate void SetDisplyDelegate(byte[] data); private int timer; private System.Windows.Forms.Timer timerTX; public PictureBox _pbTX { get; set; } public RichTextBox _rtbDisplay { get; set; } public Send() { _rtbDisplay = null; } public Send(RichTextBox RTBDISPLAY) { _rtbDisplay = RTBDISPLAY; } public void WriteData(SerialPort comPort, byte[] msg) { timerTX = new System.Windows.Forms.Timer(); timer = 150; timerTX.Interval = 25; timerTX.Tick += new EventHandler(this.timerTX_Tick); try { timerTX.Start(); comPort.Write(msg, 0, msg.Length); _rtbDisplay.BeginInvoke(new SetDisplyDelegate(RTBDisplay), new object[] { msg }); RTBDisplay(msg); } catch { MessageBox.Show("Error! Data isn't send.", "Critical Warning", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void RTBDisplay(byte[] msg) { _rtbDisplay.AppendText(System.Text.Encoding.ASCII.GetString(msg); } private void timerTX_Tick(object sender, EventArgs e) { timer=timer-timerTX.Interval*2; _pbTX.Image = global::Architect_ci8200.Properties.Resources.XSIMPLE_GREEN; if (timer == 0) { _pbTX.Image = global::Architect_ci8200.Properties.Resources.XSIMPLE_CRIMSON; timerTX.Dispose(); } else { if (timer < 0) { _pbTX.Image = global::Architect_ci8200.Properties.Resources.XSIMPLE_CRIMSON; timerTX.Dispose(); } } } } Code: class Received { private delegate void SetDisplyDelegate(byte[] data); private int timer; private System.Windows.Forms.Timer timerRX; public PictureBox _pbRX { get; set; } public RichTextBox _rtbDisplay { get; set; } public Received() { _rtbDisplay = null; } public Received(RichTextBox RTBDISPLAY) { _rtbDisplay = RTBDISPLAY; } public void ReceivedData(SerialPort comPort) { int bytes = comPort.BytesToRead; byte[] msg = new byte[bytes]; comPort.Read(msg, 0, bytes); timerRX = new System.Windows.Forms.Timer(); timer = 150; timerRX.Interval = 25; timerRX.Tick += new EventHandler(this.timerRX_Tick); timerRX.Start(); _rtbDisplay.BeginInvoke(new SetDisplyDelegate(RTBDisplay), new object[] { msg }); } private void RTBDisplay(byte[] msg) { _rtbDisplay.AppendText(System.Text.Encoding.ASCII.GetString(msg); } private void timerRX_Tick(object sender, EventArgs e) { timer = timer - timerRX.Interval * 2; _pbRX.Image = global::Architect_ci8200.Properties.Resources.XSIMPLE_GREEN; if (timer == 0) { _pbRX.Image = global::Architect_ci8200.Properties.Resources.XSIMPLE_CRIMSON; timerRX.Dispose(); } else { if (timer < 0) { _pbRX.Image = global::Architect_ci8200.Properties.Resources.XSIMPLE_CRIMSON; timerRX.Dispose(); } } } } E sad konacno i problem ![]() Kada posaljem podatke kod kada dodje do funkcije RTBDisplay(byte[] msg) najpre prodje linije koda RTBDisplay funkcije u klasi class Received a atim tek onda prodje linije koda RTBDisplay() klase class Send. Pritom mi timerTX ispravno radi, a timerRX ne. Naime, kada pratim liniju koda prilikom prijema podataka on prodje funkciju DataReceived() klase class Received ali ne ucitava funkciju RTBDisply() iste funkcije i ne pokrece event timerRX_Tick. Kako bi mogao ovaj problem resiti? Da li je mozda jednood resenja ubaciti, mada je meni nejasno kao to izvesti, da se prijem podataka vrsi kroz jednu nit a slanje kroz drugu.... Imali neko nekakvu ideju? Malo sam bio opsiran.....ali problem je takve prirode ![]() Ranije na ovom forumu sam imao savet da u aplikaciju ubacim BackGraundWorker i da preko njega probam prijem i slanje podataka ali mi nije jasno kako bi mogao njega uklopiti u ovaj kod? [Ovu poruku je menjao bigguy dana 17.01.2010. u 19:15 GMT+1] |