c# Serial DataReceived very slow - c#

I've trying to communicate with an Arduino Due in C#. The communikation works quite well, but my DataReceived handler needs about 1 second to react. This is my problem because I have to send up to 1 billion (1*10E9) commands.
If I activate a DEBUG Setting in the Arduino, it tells me that it's need 64 Milliseconds for a command. I think the C# the App should get it no later than 80 Milliseconds after sending it.
Here is a Part of the Code:
StopWatch s1 = new StopWatch();
private void Open_Port()
{
string port = null;
int baud = 0;
bool ERR = false;
if ((COM_cb.SelectedItem != null) | (BAUD_cb.SelectedItem != null))
{
port = this.COM_cb.GetItemText(this.COM_cb.SelectedItem);
baud = Convert.ToInt32(this.BAUD_cb.GetItemText(this.BAUD_cb.SelectedItem));
ERR = false;
}
else
{
ERR = true;
System.Windows.Forms.MessageBox.Show("Error Msg");
}
if (ERR == false)
{
serialPort1.PortName = port;
serialPort1.BaudRate = baud;
serialPort1.Open();
}
if (serialPort1.IsOpen)//Kalibrieren der Buttons
{
OPEN_btn.Enabled = false;
CLOSE_btn.Enabled = true;
textBox1.ReadOnly = false;
ERR = true;
}
}
private void Print_Click(object sender, EventArgs e) // start
{
Thread t = new Thread(transmit_pic);
t.Start();
}
private void DataReceivedHandler(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
s1.Stop();
//Till this line it take 1 Second after sending
//string t = "";
int byt = serialPort1.BytesToRead;
byte[] buffer = new byte[1];
for (int i = 0; i < byt; i++)
{
serialPort1.Read(buffer, 0, 1);
if(buffer[0] == '0') {
got_answer = true;
}
//t += (char)buffer[0];
}
//RxString= t;
//this.Invoke(new EventHandler(DisplayText));
}
private void sendAktion(int[,] data)
{
string s = int_to_string(data, false);
Console.Write("Send->");
serialPort1.Write(s);
s1.Start();
got_answer = false;
int i = 0;
while (!got_answer) { i++; } //wait for answer
i = 0;
Console.WriteLine("back again ");
}
private void transmit_pic()
{
stop = false;
Bitmap bm = new Bitmap(img);
if (!serialPort1.IsOpen)
{
MessageBox.Show("Open the Serial Port first!");
}
else
{
int size_X = bm.Width;
int size_Y = bm.Height;
for (int h = 0; h < size_Y; h++)
{
for (int w = 0; w < size_X; w++)
{
if(/*somthing happend*/){
//get data...
sendAktion(data)
}
}
}
Console.WriteLine("DONE");
}
}
Does anyone an Idea why c# needs so long to call the datahandler?
Sincere regards,
Fabian Harmsen
UPDATE
- Added comment to DataHandler (24.02.2016 16:30 Europa/Berlin)

The problem lies in the serialPort1_DataReceived received data handler.
I ran a separate thread with a while(true) loop and serial.ReadLine(), all works perfectly.
Hope someone else doesn't need to spend 3 hours fixing this.
using System.Threading;
public void main()
{
setup();
Thread readThread = new Thread(Read);
readThread.Start();
}
public void Read()
{
while(true)
{
try
{
string message = serialPort1.ReadLine();
}
catch (Exception)
{ }
}

Related

C# InvaildOperationException Collection was modified

I am having an issue with my C# application, it runs fine or x amount of minutes but hits an error at some point which complains about 'InvaildOperationException Collection was modified'. I am quite new to C# and i am unable to find the solution even after reading other posts.
From what i can tell after reading the posts it is something to do with my for loop, could anyone be so kind as to tell me what i have done wrong.
The error i think is caused by the UpdateGraph function.
The code is designed to connect to a Cisco router and get the cellular data via Serial and show it in a graph and richTextBox which is all working minus the error i get at some point :(
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Threading;
using System.Timers;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
namespace Cisco_Cellular_Diagnostics
{
public partial class Form1 : Form
{
SerialPort serialPort;
string[] ports;
string rawStrings;
int ComPort_ComboBoxIndex;
bool serialIsOpen = false;
bool autoScroll = false;
readonly String executingFolder = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
TextWriter txtFile;
List<int> bandwidthArray = new List<int>();
List<int> rssiArray = new List<int>();
List<int> rsrpArray = new List<int>();
List<int> rsrqArray = new List<int>();
List<int> snrArray = new List<int>();
List<int> nearbyCellsArray = new List<int>();
private static System.Timers.Timer pollingTimer;
public Form1()
{
InitializeComponent();
ports = SerialPort.GetPortNames();
ToolTip toolTip1 = new ToolTip
{
AutoPopDelay = 5000,
InitialDelay = 500,
ReshowDelay = 500,
ShowAlways = true
};
ComPortComboBox.Items.AddRange(ports);
ComPortComboBox.SelectedIndex = 0;
autoScroll = true;
pollingTimer = new System.Timers.Timer(5000);
pollingTimer.Elapsed += new ElapsedEventHandler(SendCellularCmd);
Console.WriteLine("executingFolder = " + executingFolder);
String fileDate = DateTime.Today.ToString("d").Replace("/", "-");
txtFile = new StreamWriter(executingFolder + "\\Cisco Celluar log " + fileDate + ".txt", true);
LoadChart();
}
private void LoadChart()
{
var chart = chart1.ChartAreas[0];
chart.AxisX.IntervalType = DateTimeIntervalType.Number;
chart.AxisX.LabelStyle.Format = "";
chart.AxisY.LabelStyle.Format = "";
chart.AxisX.LabelStyle.IsEndLabelVisible = true;
chart.AxisX.Minimum = 0;
chart.AxisY.Minimum = -128;
chart.AxisY.Maximum = 128;
chart.AxisX.Interval = 1;
chart.AxisY.Interval = 16;
chart1.Series[0].IsVisibleInLegend = false;
chart.AxisX.Title = "Reading";
chart.AxisY.Title = "dB";
//chart1.Series[0].XValueType = ChartValueType.DateTime;
chart1.Series.Add("Bandwidth");
chart1.Series["Bandwidth"].ChartType = SeriesChartType.Line;
chart1.Series["Bandwidth"].Color = Color.Green;
chart1.Series["Bandwidth"].BorderWidth = 8;
chart1.Series.Add("RSSI");
chart1.Series["RSSI"].ChartType = SeriesChartType.Line;
chart1.Series["RSSI"].Color = Color.Blue;
chart1.Series["RSSI"].BorderWidth = 8;
chart1.Series.Add("RSRP");
chart1.Series["RSRP"].ChartType = SeriesChartType.Line;
chart1.Series["RSRP"].Color = Color.Yellow;
chart1.Series["RSRP"].BorderWidth = 8;
chart1.Series.Add("RSRQ");
chart1.Series["RSRQ"].ChartType = SeriesChartType.Line;
chart1.Series["RSRQ"].Color = Color.Red;
chart1.Series["RSRQ"].BorderWidth = 8;
chart1.Series.Add("SNR");
chart1.Series["SNR"].ChartType = SeriesChartType.Line;
chart1.Series["SNR"].Color = Color.Purple;
chart1.Series["SNR"].BorderWidth = 8;
chart1.Series.Add("Nearby cells");
chart1.Series["Nearby cells"].ChartType = SeriesChartType.Line;
chart1.Series["Nearby cells"].Color = Color.DarkGray;
chart1.Series["Nearby cells"].BorderWidth = 8;
chart1.Series["Bandwidth"].Points.AddXY(0, 0);
chart1.Series["RSSI"].Points.AddXY(0, 0);
chart1.Series["RSRP"].Points.AddXY(0, 0);
chart1.Series["RSRQ"].Points.AddXY(0, 0);
chart1.Series["SNR"].Points.AddXY(0, 0);
chart1.Series["Nearby cells"].Points.AddXY(0, 0);
}
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
BeginInvoke((MethodInvoker)delegate ()
{
rawStrings += indata;
//txtFile.Write(indata);
//txtFile.WriteLine(DateTime.Now + "\n");
ReceivedDataRichTextBox.AppendText(indata);
if (autoScroll)
ReceivedDataRichTextBox.ScrollToCaret();
});
}
private void OpenSerial_Click(object sender, EventArgs e)
{
ComPort_ComboBoxIndex = ComPortComboBox.SelectedIndex;
if (ComPort_ComboBoxIndex >= 0 && !serialIsOpen)
{
try
{
string selectedCOM = ComPortComboBox.SelectedItem.ToString();
serialPort = new SerialPort(selectedCOM, 9600);
serialPort.ReadTimeout = 3000;
serialPort.Parity = Parity.None;
serialPort.StopBits = StopBits.One;
serialPort.DataBits = 8;
serialPort.Handshake = Handshake.None;
serialIsOpen = true;
serialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);
OpenSerialOne.Text = "Close Serial";
serialPort.Open();
LogIntoCLI();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
else if (serialIsOpen)
{
try
{
serialPort.Write("exit");
serialPort.Close();
txtFile.Close();
pollingTimer.Enabled = false;
serialIsOpen = false;
OpenSerialOne.Text = "Open Serial";
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
else
{
MessageBox.Show("Error, check the baud Rate and COM port is selected and try again.");
}
}
private void LogIntoCLI()
{
if (serialIsOpen)
{
try
{
serialPort.Write("\r");
Thread.Sleep(2000);
serialPort.Write("\r"); // "exit\r"
Thread.Sleep(2000);
serialPort.Write("enable\r");
Thread.Sleep(3000);
serialPort.Write("met0cean\r");
Thread.Sleep(2000);
pollingTimer.Enabled = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
private void SendCellularCmd(object sender, ElapsedEventArgs e)
{
ExtractData();
serialPort.Write("show cell 0 radio\r");
Console.WriteLine("sending command...");
}
private void ExtractData()
{
try
{
txtFile.Write(rawStrings);
txtFile.WriteLine(DateTime.Now + "\n");
String[] listOfStrings = rawStrings.Split('\n');
rawStrings = "";
foreach (String value in listOfStrings)
{
String[] strlist = value.Split(' ');
if (value.IndexOf("Bandwidth") >= 0 && strlist.Length == 5)
{
if (int.TryParse(strlist[3], out int extractedValue))
UpdateGraph(extractedValue, "Bandwidth", ref bandwidthArray);
}
else if (value.IndexOf("RSSI") >= 0 && strlist.Length == 5)
{
if (int.TryParse(strlist[3], out int extractedValue))
UpdateGraph(extractedValue, "RSSI", ref rssiArray);
}
else if (value.IndexOf("RSRP") >= 0 && strlist.Length == 5)
{
if (int.TryParse(strlist[3], out int extractedValue))
UpdateGraph(extractedValue, "RSRP", ref rsrpArray);
}
else if (value.IndexOf("RSRQ") >= 0 && strlist.Length == 5)
{
if (int.TryParse(strlist[3], out int extractedValue))
UpdateGraph(extractedValue, "RSRQ", ref rsrqArray);
}
else if (value.IndexOf("SNR") >= 0 && strlist.Length == 5)
{
if (int.TryParse(strlist[3], out int extractedValue))
UpdateGraph(extractedValue, "SNR", ref snrArray);
}
else if (value.IndexOf("nearby cells") >= 0 && strlist.Length == 6)
{
if (int.TryParse(strlist[5], out int extractedValue))
UpdateGraph(extractedValue, "Nearby cells", ref nearbyCellsArray);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
private void UpdateGraph(int a_value, String a_ID, ref List<int> a_List)
{
try
{
// keep the list count to 20 items
if (a_List.Count == 20)
a_List.RemoveAt(0);
a_List.Add(a_value);
// clear chart and add items
chart1.Series[a_ID].Points.Clear();
for (int i = 0; i < a_List.Count; i++)
{
chart1.Series[a_ID].Points.AddXY(i, a_List[i]);
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
if (e.CloseReason == CloseReason.WindowsShutDown) return;
// Confirm user wants to close
switch (MessageBox.Show(this, "Are you sure you want to close?", "Closing Application", MessageBoxButtons.YesNo))
{
case DialogResult.No:
e.Cancel = true;
break;
default:
try
{
txtFile.Close();
serialPort.Write("exit");
serialPort.Close();
pollingTimer.Enabled = false;
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
break;
}
}
private void PollingTimeNumericUpDown_ValueChanged(object sender, EventArgs e)
{
pollingTimer.Interval = Convert.ToDouble(PollingTimeNumericUpDown.Value);
}
private void ClearDataButton_Click(object sender, EventArgs e)
{
ReceivedDataRichTextBox.Clear();
chart1.Series["Bandwidth"].Points.Clear();
chart1.Series["RSSI"].Points.Clear();
chart1.Series["RSRP"].Points.Clear();
chart1.Series["RSRQ"].Points.Clear();
chart1.Series["SNR"].Points.Clear();
chart1.Series["Nearby cells"].Points.Clear();
chart1.Series["Bandwidth"].Points.AddXY(0, 0);
chart1.Series["RSSI"].Points.AddXY(0, 0);
chart1.Series["RSRP"].Points.AddXY(0, 0);
chart1.Series["RSRQ"].Points.AddXY(0, 0);
chart1.Series["SNR"].Points.AddXY(0, 0);
chart1.Series["Nearby cells"].Points.AddXY(0, 0);
}
private void SendManualCmd_Click(object sender, EventArgs e)
{
try
{
serialPort.Write(textBox1.Text + "\r");
textBox1.Clear();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
private void ReloadComPortsButton_Click(object sender, EventArgs e)
{
ComPortComboBox.Items.Clear();
ports = SerialPort.GetPortNames();
ComPortComboBox.Items.AddRange(ports);
}
private void ComComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
// CiscoComPort = ComPortComboBox.SelectedItem.ToString();
}
}
}

Serial Port Unauthorized Exception

I am trying to access RFID Reader through Arduino application which gives me the right output on control monitor.
But when I tried to access it through visual studio C#, it works only once and then gives me access is denied! And also stopped working on Arduino IDE.
//Function to initialize serial port
SerialPort RFIDPort
public SerialPort initializeRFIDPort()
{
try
{
RFIDPort = new SerialPort("COM4",9600,Parity.None,8, StopBits.One);
if (RFIDPort.IsOpen)
RFIDPort.Close();
if(!RFIDPort.IsOpen)
RFIDPort.Open();
}
catch (UnauthorizedAccessException ex) {MessageBox.Show( ex.Message); }
catch (Exception)
{
RFIDPort = null;
}
return RFIDPort;
}
I put the function here:
public products()
{
InitializeComponent();
initializeRFIDPort();
}
There is two scan button the first one for scanning and then add data to the database and the second button is to scan and search for data
private void ScanButton_Click(object sender, EventArgs e)
{
try
{
scanButtonIsClicked = true;
if (RFIDPort.IsOpen)
{
RFIDPort.DataReceived += serialPort1_DataReceived;
textBox1.Text = "";
}
else
MessageBox.Show("RFID Reader is not connected!");
}
catch (System.Exception)
{
MessageBox.Show("Please Try Again");
}
}
private void Searchbutton_Click(object sender, EventArgs e)
{
scansearchbtn = true;
scanButtonIsClicked = false;
try
{
if (RFIDPort.IsOpen)
{
RFIDPort.DataReceived += serialPort1_DataReceived;
textBox2.Text = "";
}
else
{
MessageBox.Show("RFID Reader is not connected!");
}
}
catch (IOException)
{
MessageBox.Show("Please reconnect your device ");
}
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
try
{
string line = RFIDPort.ReadLine();
if (scanButtonIsClicked == true)
this.BeginInvoke(new LineReceivedEvent(LineReceived), line);
else
this.BeginInvoke(new LineReceivedEvent(Line2Received), line);
}
catch (TimeoutException) { }
catch (Exception){ MessageBox.Show("Can't Read from RFID Device.Please try again"); }
}
private delegate void LineReceivedEvent(string line);
private void LineReceived(string line)
{
textBox2.Text = line;
}
private void Line2Received(string line)
{
textBox1.Text = line;
}
And then I closed serial port in Forum-Closing.
Please if anyone can lead me to the right way. I have try many times and it works randomly!
On Aruino side this is my code:
#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class
MFRC522::MIFARE_Key key;
// Init array that will store new NUID
byte nuidPICC[10];
void setup()
{
Serial.begin(9600);
SPI.begin(); // Init SPI bus
rfid.PCD_Init(); // Init MFRC522
for (byte i = 0; i < 6; i++)
{
key.keyByte[i] = 0xFF;
}
printHex(key.keyByte, MFRC522::MF_KEY_SIZE);
Serial.println();
}
void loop()
{
if ( ! rfid.PICC_IsNewCardPresent())
return;
if ( ! rfid.PICC_ReadCardSerial())
return;
// Serial.print(F("PICC type: "));
MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
// Serial.println(rfid.PICC_GetTypeName(piccType));
// Check is the PICC of Classic MIFARE type
if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI && piccType !=
MFRC522::PICC_TYPE_MIFARE_1K && piccType != MFRC522::PICC_TYPE_MIFARE_4K)
{
Serial.println(F("Your tag is not of type MIFARE Classic."));
return;
}
// Store NUID into nuidPICC array
for (byte i = 0; i < 4; i++)
{
nuidPICC[i] = rfid.uid.uidByte[i];
}
printHex(rfid.uid.uidByte, rfid.uid.size);
Serial.println();
// Halt PICC
rfid.PICC_HaltA();
// Stop encryption on PCD
rfid.PCD_StopCrypto1();
}
void printHex(byte *buffer, byte bufferSize)
{
for (byte i = 0; i < bufferSize; i++) {
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
Serial.print(buffer[i], HEX);
}
}

How to add realtime data from OPC client to user control using c#

I created an OPC client to connect to KepServerEX, I got realtime data from KepServerEX and now I want to add realtime data to user control that contains a textbox.
Realtime data will be updated via value_changed event.
I created Windows Form Application and added textbox to Form to display realtime value, I can not post images here.
This is my code:
namespace OPC_Client
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
OPCServer KepServer;
OPCGroups KepGroups;
OPCGroup KepGroup;
OPCItems KepItems;
OPCItem KepItem;
string strHostIP = "";
string strHostName = "";
bool opc_connected = false;
int itmHandleClient = 0;
int itmHandleServer = 0;
private bool CreateGroup()
{
try
{
KepGroups = KepServer.OPCGroups;
KepGroup = KepGroups.Add("OPCDOTNETGROUP");
SetGroupProperty();
KepGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange);
KepGroup.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(KepGroup_AsyncWriteComplete);
KepItems = KepGroup.OPCItems;
}
catch (Exception)
{
return false;
}
return true;
}
private void SetGroupProperty()
{
KepServer.OPCGroups.DefaultGroupIsActive = true;
KepServer.OPCGroups.DefaultGroupDeadband = 0;
KepGroup.UpdateRate = 1000;
KepGroup.IsActive = true;
KepGroup.IsSubscribed = true;
}
private void RecurBrowse(OPCBrowser OPCBrowser)
{
OPCBrowser.ShowBranches();
OPCBrowser.ShowLeafs(true);
listBox1.Items.Clear();
foreach (object turn in OPCBrowser)
{
bool bl = turn.ToString().Contains("System") ;
if (bl == false)
{
if (!Regex.IsMatch(turn.ToString(), #"^(\w+\.\w+\.\w+)$"))
{
}
else
{
listBox1.Items.Add(turn.ToString());
}
}
}
}
private bool ConnectRemoteServer(string remoteServerIP, string remoteServerName)
{
try
{
KepServer.Connect(remoteServerName, remoteServerIP);
}
catch (Exception ex)
{
MessageBox.Show(""+ex);
return false;
}
return true;
}
// Write the TAG value when executed event
void KepGroup_AsyncWriteComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array Errors)
{
lblState.Text = "";
for (int i = 1; i <= NumItems; i++)
{
lblState.Text += "Tran:" + TransactionID.ToString() + " CH:" + ClientHandles.GetValue(i).ToString() + "Error:" + Errors.GetValue(i).ToString();
}
}
void KepGroup_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
{
for (int i = 1; i <= NumItems; i++)
{
if (Qualities.GetValue(i).ToString() == "192")
{
// add realtime value to texbox to display
txtTagValue.Text = ItemValues.GetValue(i).ToString();
txtQualities.Text = Qualities.GetValue(i).ToString();
txtTimeStamps.Text = TimeStamps.GetValue(i).ToString();
}
else
{
MessageBox.Show("disconnected to opc server");
txtQualities.Text = Qualities.GetValue(i).ToString();
txtTimeStamps.Text = TimeStamps.GetValue(i).ToString();
}
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
if (itmHandleClient != 0)
{
Array Errors;
OPCItem bItem = KepItems.GetOPCItem(itmHandleServer);
int[] temp = new int[2] { 0, bItem.ServerHandle };
Array serverHandle = (Array)temp;
KepItems.Remove(KepItems.Count, ref serverHandle, out Errors);
}
itmHandleClient = 1;
KepItem = KepItems.AddItem(listBox1.SelectedItem.ToString(), itmHandleClient);
itmHandleServer = KepItem.ServerHandle;
}
catch (Exception err)
{
itmHandleClient = 0;
txtTagValue.Text = "Error ox";
txtQualities.Text = "Error ox";
txtTimeStamps.Text = "Error ox";
MessageBox.Show("The reserved for system entry:" + err.Message, "message");
}
}
private void Form1_Load(object sender, EventArgs e)
{
//GetLocalServer();
KepServer = new OPCServer();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (!opc_connected)
{
return;
}
if (KepGroup != null)
{
KepGroup.DataChange -= new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange);
}
if (KepServer != null)
{
KepServer.Disconnect();
KepServer = null;
}
opc_connected = false;
}
private void btnSetGroupPro_Click(object sender, EventArgs e)
{
SetGroupProperty();
}
private void btnConnLocalServer_Click(object sender, EventArgs e)
{
try
{
if (!ConnectRemoteServer(txtRemoteServerIP.Text.Trim(), "KEPware.KEPServerEx.V5"))
{
return;
}
btnSetGroupPro.Enabled = true;
opc_connected = true;
GetServerInfo();
RecurBrowse(KepServer.CreateBrowser());
if (!CreateGroup())
{
return;
}
}
catch (Exception ex)
{
MessageBox.Show("" + ex);
}
}
private void btnWrite_Click(object sender, EventArgs e)
{
OPCItem bItem = KepItems.GetOPCItem(itmHandleServer);
int[] temp = new int[2] { 0, bItem.ServerHandle };
Array serverHandles = (Array)temp;
Object[] valueTemp = new Object[] { "", txtWriteTagValue.Text };
Array values = (Array)valueTemp;
Array Errors;
int cancelID;
KepGroup.AsyncWrite(1, ref serverHandles, ref values, out Errors, 2009, out cancelID);
GC.Collect();
}
}
}
Now I want to create some User Controls to display some tag values.What should I do?
This is a pretty big topic in itself, but I have implemented such a beast a few years back in C#, also using KepServerEx.
Without seeing your code it's a bit difficult for me to understand what you have done so far, but the general idea is that you want to handle the OPCGroup.DataChange event. From there you have to "dispatch" the changed value to the proper TextBox.
Of course, you have to setup your OPCServer, your OPCGroup(s) and so on.
I created a library for this, and it was some extensive work required, so I'm afraid it can't really be answered in one Q&A like here.
If you have a very specific question, please open another one and I'll try to answer more specifically.
Cheers

incomplete header with socket c#

Hi I've try to send and http request to a Shoutcast stream site and then read response,
I've this two sources one is the main ( I've tested with wpf) and other is a little
helper for socket... well all works, with localhost and other site
but when I try to send a request to "209.9.238.6:6042" the header in response is never
complete but truncked.
I've done a lot of test but nothing it works only with a Thread.sleep(200);
between the send and receive look at (1), so it seems that listen() come too early and
only a part is downloaded...
can You help me?
main.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void connectionButton_Click(object sender, RoutedEventArgs e)
{
var url = "209.9.238.6:6042";
var sockHelp = new SocketHelper(url);
sockHelp.onConnect += sockHelp_onConnect;
sockHelp.connect();
}
void testDebug(string str) {
Action action = () => debugTxt.Text = str;
Dispatcher.BeginInvoke(action);
}
void sockHelp_onConnect(object sender, SocketHelperEventArgs e)
{
var sockHelp = sender as SocketHelper;
testDebug("Connected");
var header = "";
header+="GET / HTTP/1.0\r\n";
header+="Accept: */*\r\n";
header+="Host: 209.9.238.6\r\n";
header+="Connection: close\r\n\r\n";
sockHelp.onSend += sockHelp_onSend;
sockHelp.sendAsync(Encoding.UTF8.GetBytes(header));
}
private void sockHelp_onSend(object sender, SocketAsyncEventArgs e)
{
var sockHelp = sender as SocketHelper;
sockHelp.onReceive+=sockHelp_onReceive;
//Thread.Sleep(200); (1) uncomment this line... to make works
sockHelp.listen();
}
void sockHelp_onReceive(object sender, SocketAsyncEventArgs arg_)
{
testDebug("Receiving");
var t = Encoding.UTF8.GetString(arg_.Buffer);
var idx = IndexOf(arg_.Buffer, new byte[] { 0x0d, 0x0a, 0x0d, 0x0a });
if (idx < 0)
{
testDebug(Encoding.UTF8.GetString(arg_.Buffer));
return ;
}
byte[] binBuff = new byte[idx + 1];
System.Buffer.BlockCopy(arg_.Buffer, 0, binBuff, 0, idx + 1);
testDebug(Encoding.UTF8.GetString(binBuff));
}
private int IndexOf(byte[] searchIn, byte[] searchFor)
{
if ((searchIn != null) && (searchIn != null))
{
if (searchFor.Length > searchIn.Length) return 0;
for (int i = 0; i < searchIn.Length; i++)
{
int startIndex = i;
bool match = true;
for (int j = 0; j < searchFor.Length; j++)
{
if (searchIn[startIndex] != searchFor[j])
{
match = false;
break;
}
else if (startIndex < searchIn.Length)
{
startIndex++;
}
}
if (match)
return startIndex - searchFor.Length;
}
}
return -1;
}
}
}
helper.cs
namespace TestSocket
{
/// <summary>
/// </summary>
public class SocketHelperEventArgs : EventArgs
{
public SocketHelperEventArgs(SocketError se)
{
socketError = se;
}
public SocketHelperEventArgs() { }
SocketError socketError;
SocketAsyncEventArgs args;
}
public class SocketHelper
{
byte[] _buffer = new byte[1024*2];
SocketAsyncEventArgs _args = new SocketAsyncEventArgs();
readonly Socket _socket;
public event EventHandler<SocketHelperEventArgs> onError;
public event EventHandler<SocketHelperEventArgs> onConnect;
public event EventHandler<SocketAsyncEventArgs> onReceive;
public event EventHandler<SocketAsyncEventArgs> onSend;
public SocketHelper(string url)
{
int port=0;
string[] addressVector = url.Split(':');
if (addressVector.Length == 1)
port = 80;
else
port = int.Parse(addressVector[1]);
_args.RemoteEndPoint = new DnsEndPoint(addressVector[0], port); ;
_args.Completed += SocketAsyncEventArgs_Completed;
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
public void listen()
{
_args.SetBuffer(_buffer, 0, _buffer.Length);
_socket.ReceiveAsync(_args);
}
public void connect()
{
bool completesAsynchronously = _socket.ConnectAsync(_args);
if (!completesAsynchronously)
{
SocketAsyncEventArgs_Completed(_args.ConnectSocket, _args);
}
}
public void sendAsync(byte[] data) {
_args.SetBuffer(data, 0, data.Length);
_socket.SendAsync(_args);
}
private void SocketAsyncEventArgs_Completed(object sender, SocketAsyncEventArgs e)
{
// check for errors
if (e.SocketError != SocketError.Success)
{
if (onError != null) onError(this, new SocketHelperEventArgs(e.SocketError));
CleanUp(e);
return;
}
switch (e.LastOperation)
{
case SocketAsyncOperation.Connect:
if (onConnect != null) onConnect(this, EventArgs.Empty as SocketHelperEventArgs);
break;
case SocketAsyncOperation.Send:
if (onSend!= null) onSend(this, e);
break;
case SocketAsyncOperation.Receive:
if (onReceive != null) onReceive(this,e);
break;
}
}
private void CleanUp(SocketAsyncEventArgs e)
{
if (e.ConnectSocket != null)
{
e.ConnectSocket.Shutdown(SocketShutdown.Both);
e.ConnectSocket.Close();
}
}
}
}
You seem to assume that you will get the whole response in one read. That's not correct. You will get some data from the socket when data is available. You need to detect whether there's more data to come according to the application-level protocol - HTTP or ICY or whatever you are using, and, if so, re-arm the asynchronous read.
Right now you are consuming whatever happens to be in the socket receive buffer. Waiting seems to work just because more data piles up there after that timeout, but there's no guarantee you are getting everything.

Timer in separate thread

I want to create a timer in a separate thread, but I'm not sure how to do it.
The timer should stop after clicking button a button.
Below I have an example that mostly works but it stops sometimes for 1-2 seconds when the loop is executing. So I guess I have to put it in a separate thread? This is what I've tried:
private void buttonStop_Click(object sender, EventArgs e)
{
timer1.Stop();
}
public void TimeThread()
{
th = new Thread(new ThreadStart(Timer));
th.Start();
}
public void Timer()
{
var delta = DateTime.Now - startTime;
textBoxSeconds.Text = delta.Seconds.ToString("n0");
textBoxMinutes.Text = Math.Floor(delta.TotalMinutes).ToString("n0");
}
EDIT:
So here is all the code that I have, still not exactly sure how to put the timer in separate thread.
namespace Imgur
{
public partial class Form1 : Form
{
bool flag = true;
int downloadedNumber = 0;
private DateTime startTime;
public Form1()
{
InitializeComponent();
}
public void buttonStart_Click(object sender, EventArgs e)
{
buttonStart.Enabled = false;
buttonStop.Enabled = true;
if (!flag)
{
flag = true;
}
startTime = DateTime.Now;
timer1.Start();
for (int i=0;i<100000 && flag;i++)
{
WebClient webClient = new WebClient();
string pic1 = rnd_str(5);
string pic2 = ".jpg";
string picture = pic1 + pic2;
//********** GETTING SIZE OF IMAGE ***********
Size sz = GetSize("http://i.imgur.com/" + picture);
string imageSize = (sz.Width.ToString() + " " + sz.Height.ToString()); ;
//********************************************
if(imageSize != "161 81")
{
webClient.DownloadFile("http://i.imgur.com/" + picture, #"e:\test\" + picture);
richTextBox1.Text += String.Format("Downloaded picture: {0}\r\n", picture);
downloadedNumber++;
textBoxDownloadedNumber.Text = string.Format("{0}", downloadedNumber);
}
webClient.Dispose();
Application.DoEvents();
if (i == 999995)
{
flag = false;
}
}
richTextBox1.Text += "End Dowloaded Session \n";
buttonStart.Enabled = true;
buttonStop.Enabled = false;
timer1.Stop();
}
public static Size GetSize(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.Accept = "image/gif";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream s = response.GetResponseStream();
Bitmap bmp = new Bitmap(s);
Size sz = new Size(bmp.Width, bmp.Height);
return sz;
}
public static string rnd_str(int liczba_liter)
{
Random r = new Random();
int char_type;
string return_string = "";
int i =0;
for (i = 0; i < liczba_liter; i++)
{
if (r.Next(1, 3) == 1)
{
char_type = r.Next(1, 4);
switch (char_type)
{
case 1:
return_string += (char)r.Next(48, 58); // convertion int -> ASCII character; 48-57 are ASCII digits
break;
case 2:
return_string += (char)r.Next(97, 123); // convertion int -> ASCII character; as above but small letters
break;
case 3:
return_string += (char)r.Next(65, 91); // as above; large letters
break;
default:
i -= 1;
break;//do not add any letter if no type is allowed
}
}
else
{
i -= 1;
return_string += "";
}
}
return return_string;
}
private void buttonStop_Click(object sender, EventArgs e)
{
flag = false;
buttonStart.Enabled = true;
timer1.Stop();
}
public void timer1_Tick(object sender, EventArgs e)
{
var delta = DateTime.Now - startTime;
textBoxSeconds.Text = delta.Seconds.ToString("n0");
textBoxMinutes.Text = Math.Floor(delta.TotalMinutes).ToString("n0");
}
}
}
In your code it seems there is no connection between the timer and the print of the time passed.
You need to pay attention because it isn't possible to change GUI elements from another thread that isn't the main one.
To do this you need to use Invoke in WinForms
if (control.InvokeRequired)
{
control.Invoke(new SetControlPropertyThreadSafeDelegate(SetControlPropertyThreadSafe), new object[] { control, propertyName, propertyValue });
}
else
{
control.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, control, new object[] { propertyValue });
}
or dispatcher in WPF/SL - http://www.switchonthecode.com/tutorials/working-with-the-wpf-dispatcher
In order to use another thread and you have some options:
Threadpool (On .Net 4) - http://msdn.microsoft.com/en-us/library/3dasc8as(v=vs.80).aspx
Thread class - http://msdn.microsoft.com/en-us/library/aa645740(v=vs.71).aspx
BackgroundWorker Class - http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx
The 3rd option is the easiest if you don't know how to work with theards
There're tree Timers in .Net take a look at the following article and select correct timer looks like you need timer from System.Threading, not from System.Windows.Forms.

Categories