I'm mostly a C++ programmer looking to port some code over to C# but unfortunately developing for the hololens has forced me to use UWP. The following code has been working just fine for receiving some very fast UDP broadcasts (~250-500 per second)
while ( listener.Available > 0 )
{
byte[] bytes = listener.Receive(ref groupEP);
position = BitConverter.ToSingle(bytes, 0);
}
and as far as the "getting it to work" stage it's done. But moving over to UWP I'm apparently no longer allowed to use UdpClient and now forced to use "DatagramSocket" which has an async callback rather than giving you control of when you check for/process your data. I'm not generally against a callback vs playing catchup each update loop but the DatagramSocket doing roughly the same thing is causing flickering in rendering and generally just not working at all. I've tried about a thousand different ways of re-organizing my callback, but currently it looks like this:
async void MessageReceived(DatagramSocket socket, DatagramSocketMessageReceivedEventArgs eventArguments)
{
try
{
lock (this)
{
DataReader broadcastReader = eventArguments.GetDataReader();
asyncPosition = broadcastReader.ReadSingle();
}
}
catch (Exception exception)
{
}
}
I then in my update loop have this at the end, and position is used in my render routine
lock (this)
{
position = asyncPosition;
}
No matter what I put anywhere in the program or how I try and organize the callback and the variables used I can't seem to find any way to get this to work properly, and I'd really appreciate a primer on how to properly handle a DatagramSocket
I am trying to do something very simple that does not work: With my C# application I simply want to listen for UDP packages on a specific port. With Wireshark I can see very well that the packages that I desire are received perfectly fine (CRC and everything ok).
However, none of the codes I found on internet work. For example this one failes as well:
private void ReceiveAsync()
{
UdpClient Client = new UdpClient(new IPEndPoint(IPAddress.Any, 51200));
try
{
Client.BeginReceive(new AsyncCallback(OnReceive), null);
}
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show(e.Message);
}
}
private static void OnReceive(IAsyncResult result)
{
System.Windows.Forms.MessageBox.Show("Simply to tell you that something was received on the port");
}
There are two ethernet network cards installed. Maybe this can be a problem? But even if I specify the IP address specifically it would not change anything.
UdpClient Client = new UdpClient(new IPEndPoint(IPAddress.Parse("10.0.0.2"), 51200));
I would be very happy about any ideas that could solve this problem. Thank you very much!
The code is fine and working - I have tested it.
You need to wait for received data, Client object exist only in ReceiveAsync
Try adding Thread.Sleep(10000)
Edit:
Thread.Sleep(1000) is not good practice since it block the thread.
it's depend on the problem/case that you are trying to solve. you may have some kind of TCP engine that handle multiple connection ,or data processing so you can say data on buffer for some other thread to work on.
If you share the problem that you are trying to solve , maybe can give better answer
Also can see the code example from MSDN - UdpClient.BeginReceive
I found this thread in here
Receive messages continuously using udpClient
May be this helps.
you should really not show a message box, think about a debug output.
save your input directly after receiving, to avoid blocking the network.
I developed a C# application for reading calls from GSM Modem. I used a timer to read the port regularly and notify me when there is a incoming call.
Now i am trying to use another timer which will write AT+CSQ -To know the signal quality, on the port and read the port for the quality value. In both the timers i used regular expressions to match and separate the data i need. Now the problem is that only my timer2 which is reading the signal quality is only working but not timer reading for incoming calls.
Timer reading signal strength:
private void tmr_sig_quality_Tick(object sender, EventArgs e)
{
if (port.IsOpen)
{
port.WriteLine("AT+CSQ");
string s= port.ReadExisting();
var match= Regex.Match(s,#"\+CSQ: (\d+),(\d+)");
if (match.Success)
{
progressBar1.Value = int.Parse(match.Groups[1].Value);
}
}
}
Timer reading incoming calls:
private void timer1_Tick(object sender, EventArgs e)
{
s = port.ReadExisting();
var match = Regex.Match(s, "RING[^\\+]*\\+CLIP:\\s*\"(?<phone>[^\"]*)\",(\\d+),\"([^\"]*)\",(\\w*),\"(\\w*)\",(\\w*)");
if (match.Success && s.Contains("RING"))
{
incall_status.Text = "Incoming Call...." + match.Groups["phone"].Value;
incall_status.Visible = true;
}
}
Why is this happening and solution please?
Two major problems. First is ReadExisting(), that will always return an empty string. Except when you are debugging and stepping through the code line by line. That gives the modem enough time to send the response. But this won't work when you run at full speed, you'll need to make a blocking call that ensures your program waits long enough to get all the returned characters. Use ReadLine() instead.
Second killer problem is that you are mixing commands. Your tmr_sig_quality_Tick() method is likely to read whatever timer1_Tick() was supposed to read. You'll need to re-think this approach. Something like a queue of commands that doesn't advance until the response to a command is received.
Not an actual answer to your question, but a general advice for communicating with a GSM modem:
Keep in mind that you have only one serial port, thus only one communication channel. A GSM modem can send spontaneous events, such as the RING, FAX, VOICE events, so there is no guarantee that when you write AT+CSQ the first reply is what you expect, i.e. the signal quality.
Having two timers like you're intending is not a good idea since you'll eventually end up with the response of one command in timer A when it was expected in B, because A read one of the spontaneous events...etc.
A much better and robust way is to have a worker thread that reads and interprets the incoming data and then distributes that in you application as needed. It can also handle the outgoing data. Use concurrent queues and some signaling mechanism (i.e. AutoResetEvent) for exchanging data with this thread, that way you get a cleaner interface to your hardware device and don't need to worry about timing and such in your application.
I've been fighting with this issue for a day and I can't find answer for it.
I am trying to read data from GPS device trough COM port in Compact Framework C#. I am using SerialPort class (actually my own ComPort class boxing SerialPort, but it adds only two fields I need, nothing special).
Anyway, I am running while loop in a separate thread which reads line from the port, analyze NMEA data, print them, catch all exceptions and then I Sleep(200) the thread, because I need CPU for other threads... Without Sleep it works fine, but uses 100% CPU.. When I don't use Sleep after few minutes the output from COM port looks like this:
GPGSA,A,3,09,12,22,17,15,27,,,,,,,2.6,1.6,2.1*3F
GSA,A,3,09,12,22,17,15,27,,,,,,,2.6,1.6,2.1*3F
A,A,3,09,12,22,17,15,27,,,,,,,2.6,1.6,2.1*3F
,18,12,271,24,24,05,020,24,14,04,326,25,11,03,023,*76
A,3,09,12,22,17,15,27,,,,,,,2.6,1.6,2.1*3F
3,09,12,22,17,15,27,,,,,,,2.6,1.6,2.1*3F
09,12,22,17,15,27,,,,,,,2.6,1.6,2.1*3F
,12,22,17,15,27,,,,,,,2.6,1.6,2.1*3F
as you can see the same message is read few times but cut.
I wonder what I'm doing wrong...
My port configuration:
port.ReadBufferSize = 4096;
port.BaudRate = 4800;
port.DataBits = 8;
port.Parity = Parity.None;
port.StopBits = StopBits.One;
port.NewLine = "\r\n";
port.ReadTimeout = 1000;
port.ReceivedBytesThreshold = 100000;
And my reading function:
private void processGps(){
while (!closing)
{
//reconnect if needed
try
{
string sentence = port.ReadLine();
//here print the sentence
//analyze the sentence (this takes some time 50-100ms)
}
catch (TimeoutException)
{
Thread.Sleep(0);
}
catch (IOException ioex)
{
//handling IO exception (some info on the screen)
}
Thread.Sleep(200);
}
}
There is some more stuff in this function like reconnection if the device is lost etc., but it is not called when the GPS is connected properly. I was trying
port.DiscardInBuffer();
after some blocks of code (in TimeoutException, after read.)
Did anyone had similar problem? I really dont know what I'm doing wrong.. The only way to get rig of it is removing the last Sleep.
For all those who have similar problem. The first issue was about overflowing the buffer. I had 4096 size of buffer and the data was just flowing trough it so I was reading corrupted sentences. Now I read all buffer at once and analyze it. First sentence is sometimes corrupted, but the rest is ok.
The second thing was the device issue. Tom Tom MkII sometimes loses connection with the device. I had to restart the GPS and find it again in Bt devices list.
Regards
There's nothing in your post to say how you are doing handshaking.
Normally you would use software (XON/XOFF) or hardware (e.g. RTS/CTS) handshaking so that the serial port will tell the transmitting to stop when it is unable to receive more data. The handshaking configuration must (of course) match the configuration of the transmitting device.
If you fail to configure handshaking correctly, you may get away with it as long as you are processing the data fast enough - but when you have a Sleep, data may be lost.
Pretty simple question this time around. I have an application that communicates with another copy of the application on another machines. One application sends a pretty constant stream of data, the other receives it.
The code to send data looks like this (where serialPort is an instance of the System.IO.Ports.SerialPorts class in C# .Net 2.0):
private void bgDataWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e){
try{
string tempStr = Convert.ToString(String.Format("{0:0.000000}", data));
serialPort.Write(tempStr); // Write "data" out to 6 decimal places
}
catch (TimeoutException){ }
catch (InvalidOperationException err){ // Port is obstructed or closed
this.Invoke((MethodInvoker)delegate{
MessageBox.Show(this, "Couldn't send wireless data:\n\n" +
err.ToString(), "NanoMETER - Wireless Error (Data)",
MessageBoxButtons.OK, MessageBoxIcon.Error);
Global.remoteEna = false;
serialPort.Close();
usingBT = false;
});
}
}
It's called on a timer. The receive code is even more straightforward:
private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) {
string buffer = serialPort.ReadExisting();
HandleInput(buffer);
}
Data gets sent and handled and it's all fine and dandy, but there's some unwanted choppiness where it's either not reliably sending data at a constant rate, or it's not picking up everything. I'm not sure if this can be fixed in my code, or if it's just the nature of having a few slow machines and a possibly shakey bluetooth connection. Any suggestions?
It's not uncommon for interns to be assigned to converting old code to a newer platform.
There are a few improvements you can make.
1) The following strategy is good when the bytes sent through the port is meant to be interpreted in blocks, such as commands. Do you have some sort of protocol? Something that dictates the format of the message you are sending. For instance, a specific delimiter to indicate the beginning and the length of the upcoming command. This allows you to quickly determine if the command was only half sent, or if there were missing bytes. Even better is to add a CRC at the end.
2) Instead of reading on a timer, base yourself on the events flagged by your serialport object. Here's an example of what i use:
//OnReceive event will only fire when at least 9 bytes are in the buffer.
serialPort.ReceivedBytesThreshold = 9;
//register the event handlers
serialPort.DataReceived += new SerialDataReceivedEventHandler(OnReceive);
serialPort.PinChanged += new SerialPinChangedEventHandler(OnPinChanged);
In the code above, i set a threshhold of 9, you should change that to whatever fits your context. Also, the Pinchanged event is something good to monitor, it will allow you to quickly identify if the cable has been disconnected. There is more on this, regarding CTSChanged but you can look it up if you are interested.
Lastly, if this doesn't help you get a little further, show an example of the problem that occured so the peolpe here can give you more help.