synchronizace   otázka

C#

Jak správně synchronizovat čtená data z RS232 (Inputs), abych je mohl použít v cyklických výpočtech v timer1_Tick() ?

Pro zobrazení na hlavním formuláři používám InvokeRequired (funkce SetText), ale jak na další data, která chci dále používat ve výpočtech?

diky

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.IO.Ports; 

namespace WindowsFormsApplication1 
{ 
// vstupni data, ktera se ctou z RS232 
public class InputData 
{ 
public int varInt; 
public char varChar; 
public object[] varOther; 

// vypreparovani dat ze stringu nacteneho z R232 
public void FromString(string xStr) 
{ 
if ((xStr != String.Empty) && (xStr.Length > 2)) 
{ 
varChar = xStr[0]; 
varInt = int.Parse(xStr.Substring(1, 2)); 
} 
} 
} 

// vystupni data, ktera zapisuji na RS232 
public class OutputData 
{ 
public int varInt; 
public string varStr; 
public object[] varOther; 

// vygenerovani stringu pro poslani na RS232 
public override string ToString() 
{ 
return string.Format("{0}={1}", varStr, varInt); 
} 
} 

public partial class Form1 : Form 
{ 
private SerialPort port; 
private InputData Inputs; 
private OutputData Outputs; 

public Form1() 
{ 
InitializeComponent(); 
} 

private void Form1_Load(object sender, EventArgs e) 
{ 
Inputs = new InputData(); 
Outputs = new OutputData(); 
port = new SerialPort("COM1"); 
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived); 
port.Open(); 
} 

void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
string InputData = port.ReadExisting(); 
Inputs.FromString(InputData); 
} 

// timer po 100ms, kde budou probíhat výpočty 
private void timer1_Tick(object sender, EventArgs e) 
{ 
// vypocty nad daty 
Outputs.varInt += Inputs.varInt + 1; 
string s2 = Inputs.varChar.ToString().ToUpper() + "blablabla"; 

// zobrazeni dat 
SetText(label1, string.Format("I.varInt={0}, O.varInt={1}", Inputs.varInt, Outputs.varInt)); 

// zapis na linku 
port.Write(Outputs.ToString()); 
} 


// pro thread-safety zobrazeni v Labelu 
delegate void SetTextCallback(Label lbl, string text); 
private void SetText(Label lbl, string text) 
{ 
if (lbl.InvokeRequired) 
{ 
SetTextCallback d = new SetTextCallback(SetText); 
this.Invoke(d, new object[] { lbl, text }); 
} 
else 
lbl.Text = text; 
} 

} 
} 
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Z tohoto vůbec není jasné, co a jak se má synchronizovat, ani tam není přístup z více vláken, aby byla synchronizace vůbec potřeba. Navíc provádět synchronizaci z Timeru je pitomost, protože ten už má synchronizaci pomocí WindowsFormsSynchronizationContext zabudovanou v sobě.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Dočetl jsem se, že v port_DataReceived se musí data synchronizovat, např. pro výpis do labelu na formu. Tak když zde budu načítat další data, tak k nim můžu v timeru normálně přistupovat bez synchronizace?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Pokud přistupujete k ovládacím prvkům z jiného vlákna než ze kterého byly vytvořeny, pak je nutná synchronizace. Jenže vy v tom handleru k žádným ovládacím prvkům nepřistupujete, takže synchronizace je zbytečná. V handleru od Timer.Tick rovněž není nutná synchronizace, protože ji má Timer zabudovanou v sobě. Zjistěte si základy než se budete pouštět do něčeho složitějšího.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

v port_DataReceived dáta ukládate do premennej, čiže nie je priamy prístup k ovládacím prvkom. K ovládacím prvkom pristupujete cez Timer, ktorý, ako tu už zaznelo, má synchronizáciu v sebe. Počul som už(nemám overené), že prehadzuje událosť Tick do UI vlákna. Teda opäť nie je potrebné Invoke. Invoke budete potrebovať, ak budete Label nastavovať v DataReceived bez použitia Timeru.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Takže jestli tomu rozumím správně, tak platí, že..?

1) v Tick není nutné synchroniovat nic

2) v dataReceive musím synchronizovat přístup k UI komponentám přes InvokeReq..

3) když v dataReceive naplním nějaký proměnný, tak v Tick k nim můžu normálně přistupovat

díky

nahlásit spamnahlásit spam 0 odpovědětodpovědět

1) Ano, pokud k datům nepřistupují ještě nějaká další vlákna pro zápis.

2) Ano, buď pomocí If InvokeRequired Then... nebo přes WindowsFormsSynchronizationContext (doporučeno).

3) Ano, pokud k datům nepřistupují ještě nějaká další vlákna pro zápis.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

díky

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback