Click here to Skip to main content
15,896,557 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi, I'm writing a program that when I click, I send various codes to a microcontroller and it sends back a response followed by a special character. My problema is that I send the first code, and I don't know how to wait until I read the whole information of the microcontroller before sending the seconde code. Here is the program:

C#
public void PuertoSerieDataReceived(object sender, SerialDataReceivedEventArgs e)
{	
	string input_data = SerialPort.ReadExisting();	
	rtbText.AppendText(input_data);					
}
		
void botonMostrarTramaClick(object sender, EventArgs e)
{			
	if (SerialPort.IsOpen)												
	{
		rtbText.Text = "";
		string string_end = "";	
		
		string code0 = "100567880000110000005181";
		string askForInformation0 = (char)2+ code0.ToString() +(char)4;
		SerialPort.Write(askForInformation0);
		
		while(input_data.EndsWith(string_end) == false)
		{
			
		} 
		
		string code1 = "100567880000110000005181";
		string askForInformation1 = (char)2+ code1.ToString() +(char)4;
		SerialPort.Write(askForInformation1);
		
		while(input_data.EndsWith(string_end) == false)
		{
			
		} 
		
		string code2 = "100567880000110000005181";
		string askForInformation2 = (char)2+ code2.ToString() +(char)4;
		SerialPort.Write(askForInformation2);
		
		while(input_data.EndsWith(string_end) == false)
		{
			
		} 
	}
}
Posted
Comments
Member 11423970 16-Feb-15 8:42am    
I don't know if there is any command that allows me to wait until the serial port sends all the data before sending the second code.
johannesnestler 16-Feb-15 8:50am    
didn't read any further after string input_data = SerialPort.ReadExisting();
you read in a local variable (maybe hiding a class-member?) this is not the same variable you use in while(input_data.EndsWith(string_end) == false. So a clear "beginner mistake". To synchronize your calls you could use Tasks with continuations (Google) or normal Event signaling (maybe create a AnswerReceived Event and fire it when Input_data matches some condition). don't use loops "to wait" - this is not plc programming...
johannesnestler 16-Feb-15 8:53am    
ah, forgot to mention, you should really spend a day on the Basics (no offense it's just obvious you come from another domain) - read about String.Format on MSDN could help constructing the communication-strings and have more readable code
Member 11423970 16-Feb-15 9:03am    
Yes, I'm a beginner with programming, so forget me if I don't get all of your answer. No loops to wait, got it. The input_data ends with an special character that doesnt' appear on this screen, so the idea is taht, read all the input data and when the symbol appears says, this is all my string of information, and send the next code to recieved another piece of data.
johannesnestler 16-Feb-15 9:14am    
I try to create some example code for you... please wait a little

Hi after reading your code again I saw you are doing it all on one thread. so a more simple solution is possible. Just call read like this:

const string m_strEND_SPECIALCHAR = "§"; // whatever your microcontroller defines as terminator char
m_serialport.ReadTo(m_strEND_SPECIALCHAR);


So you should create a new thread/task or backgroundworker on your click - send and wait for the repsonses on that thread (maybe respect timeouts) ( not in your click handler).


OT: Construct your Input strings

now:
C#
string code1 = "100567880000110000005181";
string askForInformation1 = (char)2+ code1.ToString() +(char)4;


better:
C#
string GetAskForInformationString(string code)
{
    return String.Format("{0}{1}{2}", (char) 2, code, (char) 4);
}


If you want to go for a more advanced approach maybe consider reading:
about WaitHandles and thread sync: https://msdn.microsoft.com/en-us/library/ms173179.aspx[^]
or Tasks and Continuations: https://msdn.microsoft.com/en-us/library/ee372288(v=vs.110).aspx[^]
And how to make such async code cleaner with asyc/await: https://msdn.microsoft.com/en-us/library/hh191443.aspx[^]

I hope this helps, I'd recommend go from simple to more advanced and try to learn the concepts "on the way". For shure you have to Change your code, so that it not runs on the UserInterface thread. If you click your button and sending/receiving takes some time (likely with Serial ports) your app will freeze. so use of threads is mandatory (and threading is always Kind of "complicated").

Kind regards

Johannes
 
Share this answer
 
Comments
Member 11423970 16-Feb-15 10:22am    
Very complete answer and very helpful resources. I have read them and I will work with them. I general, you are suggesting me to créate an Async Method?
johannesnestler 16-Feb-15 10:34am    
In the end, yes. Because you will have to sync the results with your GUI but not blocking it...
Member 11423970 16-Feb-15 11:00am    
Ok, thak you very much for all the help
Sergey Alexandrovich Kryukov 16-Feb-15 11:34am    
This should be a working solution, but I would not recommend that. Please see Solution 2, and the referenced answers.
—SA
johannesnestler 16-Feb-15 12:43pm    
I suggested to move the blocking calls to another thread too... But maybe I didn't formulate it good enough - thanks for your comment and the provided solution...
You can write event simpler and more maintainable code than that advised in Solution 1, if, instead of asynchronous method, you move all your serial I/O to a separate thread (at least one). Then your problem for waiting for certain data in the channel will be eliminated. You will just read unconditionally the amount of data you want. If data is not ready yet, it will block your calling thread, which is not a problem. When a portion of data you expected is received, you can notify some other thread (your main thread, UI thread, whatever) using regular thread communication (with UI threads, it would be Invoke or BeginInvoke the methods of either Control or Dispatcher).

Moreover, working with serial port in a main thread would be almost always unsafe. I really recommend you to dedicate a separate thread for serial communications (and many other kinds of communications). Even if you did not have this "waiting" problem…

As to the asynchronous approach, please see my past answers:
Async Await Multiple Telnet Servers[^],
TCP Socket - Send and receive question[^],
TcpListener, TcpClient, Ping in Visual Basic 2005[^],
problem in multithreading ? !!![^].

—SA
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900