|
Hey!
Intruduction:
I am using Framework 2.0(beta 2) and the System.IO.Ports.SerialPort class to communicat with serialport/USB devices.
I have built my serialport communication with Events, like this:
<br />
#region Create Connection<br />
serialPort = new SerialPort(serialPortSettings.getPort, serialPortSettings.getBoudRate, serialPortSettings.getParity, serialPortSettings.getDataBits, serialPortSettings.getStopBit);<br />
serialPort.DtrEnable = true;<br />
serialPort.RtsEnable = true;<br />
serialPort.ReceivedBytesThreshold = 4;<br />
serialPort.Open();<br />
#endregion<br />
<br />
serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_ReceivedEvent);<br />
SerialPort Settings that I use
Baud rate: 115200
Data bits: 8
Parity: None
Stop bit(s): 1
This is done by a special serialport thred, this to make sure that the main thread(the one that redraws the GUI and so on) not will be involved in the event firing of this serialport.
In serialPort_ReceivedEvent you can finde the folowing code:
<br />
lock (this)<br />
{<br />
if (RUNNING)<br />
{<br />
ThreadPool.QueueUserWorkItem(new WaitCallback(onDataReceived));<br />
currentRunningThreads++;
}<br />
}<br />
This function will be fired as soon as 4 bytes(ReceivedBytesThreshold) have been written to the serialport. As you can see, it will place a work in the ThreadPool and then make the current thread available for next event.
The onDataReceived looks like this.
<br />
if (RUNNING)<br />
{<br />
lock (this)<br />
{<br />
if (serialPort.BytesToRead > 0)<br />
{<br />
string data = serialPort.ReadExisting();<br />
<br />
<br />
if (data != null && data.Length > 0)<br />
{<br />
RemovePortHandlerRAW.Write(data);
RemovePortHandlerRAW.Flush();<br />
<br />
data = toolHandler.costmizeString(data, timeStamp, showCR_LFOnIncomingData);<br />
<br />
streamHandler.writeData(data);
<br />
if(SAVEDATATOFILE)<br />
rows = toolHandler.stringToArray(data);<br />
<br />
if (rows != null)<br />
{<br />
if (SAVEDATATOFILE)<br />
dataCollector.writeArrayToFile(rows);<br />
}<br />
}<br />
}<br />
}<br />
As you can see, am doing different things in this onDataReceived function, but the main part is: ReadExisting on the serialport and writes it to file to be abled to compare it with the file I am realy sending to my program by using CompareIt(http://www.grigsoft.com/)
TEST:
I have created a program that sends a 2 MB file with a serten data structure where every row ends with CRLF. This program sends one char at a time and this as fast as posible over a nullmodem cable (from laptop to my computer)
When the file is transfared to my computer from the laptop, it will be compared with the file I sent from my laptop, to ensure that no data is lost.
Test Result:
I have manage to find a good ReceivedBytesThreshold(decides how many byte that have to be written to the serialport before the event is fired) on the serialport that I don’t lose any data, but have a good CPU usage. I first tried 512, 256, 32. But all this value will result in some Dataloses in high speed. I then tested 4, and that works good(no data loses).
Why not choose 1? By choosing 1 in ReceivedBytesThreshold will result in a higher CPU usage.
Stress Test:
To ensure that no data will be lost I hade to made some stress tests.
Test 1:
I tried to move around a firefow window(web browser) with an andvance page loaded(like www.gamespot.com). By doing this I get 100% CPU usage, and if I do this as long as posible during my program is receiving data over the nullmodem cabel, this test showed that data are lost during stress test like this!!
Sometimes it could also result in an array that says that a Thread have been interupted, but I don’t realy know why?
Test 2:
By open a window in WindowsXp with some files in and the hold F5 pressed it will update the window so fast that the CPU usage will be 100%. But this will strangly not effect the data flow? No data is lost?
Problems:
As you can see, I cant get a sequre data transfer! I have tried other program with the same stress tests like the one here http://www.aggsoft.com/, but this works fine!
Maby this is I Microsoft problem, maby the serilaport in framework 2.0 is not reay finished yet?
Maby I shouldt buther with the outcome on Test1?
I have also tried to have a Thread loop instead of the events, but that dident help(same problem).
I realy need help here, It would be great if anyone else have the posibility to try the exact same thing.
Best Regards
SnowJim
|
|
|
|
|
The problem is with you using ThreadPool threads to write to the file. I'm pretty sure you expect the contents of the file to be in the same order as you sent. But using threads to write to the file will surely result in data misordering.
When you call ThreadPool.QueueUserWorkItem , the system assigns a thread to run the function. There is no guarantee that the function would complete before you get another serialPort_Received event. Imagine the case when the first thread has read the contents but before it writes to the file, there is another serialPort_Received event and that thread writes to the file first. Your file wouldn't have the contents in the right order then.
I suspect that's why you're getting strange results when the CPU is busy. When the CPU is relatively idle, it probably schedules your threads in such a way that each DataReceived event occurs after the ThreadPool thread has completed.
Regards
Senthil
_____________________________
My Blog | My Articles | WinMacro
|
|
|
|
|
Yes i understand what you mean, but thats why i am using lock so there will hofully be a sort av queue that executes the threads in the right order?
I have also tried to place the code that writes to file in the ReceivedEvent event direcly and take away the ThreadPool Thing. Like this:
<br />
lock (this)<br />
{<br />
if (RUNNING)<br />
{<br />
FILEHANDLING CODE HERE<br />
}<br />
}<br />
but this is not helping?
I have as a mentioned, tried to switch from event to a Thread Loop, and then the data cant be read in wrong order. But this results in same dataloses as with event and Threadpool.
If i understand you right, then the data will be in the file but on a diffrent place?
The CompareIt program that i am using to compare files, will show if data is moved to other parts of the txt file. And in thes cases when i have lost data, there is simply data missing from the recived file(it also got a smaller size then it would have if its contained all the data).
BestRegards
SnowJim
|
|
|
|
|
If that doesn't help, I'm not sure what the problem is. Are you sure you always get the ReceivedEvent in the first place? Also, are you sure there is nothing wrong with the code sending the messages and that it actually has sent the messages?
Regards
Senthil
_____________________________
My Blog | My Articles | WinMacro
|
|
|
|
|
Even if i shold not get the event one time, the next time it will readExisting on port, so this shold not be a problem.
And the sendingsoftware shold be working. I have used it in stress test of other serialport programs that i have downloaded, and there are no data lost?
I dont eather know way it is losing data when i am moving around window?
Cant u try det same thing? if you got a nullmodem cable?
BestRegards
SnowJim
|
|
|
|
|
If you depend on the data arriving in the exact same order it was sent, there is no easy way other than using one (1) hand-crafted thread to "listen" on the serial port.
Locking simply means that threads will not interfere with each other, it does not assure the order in which the threads will gain access.
You COULD try and use a ResetEvent in the main "queue", which is then reset in the worker-thread.
I still suggest that you try and design a single "listening worker" which should be written in a way that has it handle the events "one by one". That will cost you some speed, but is easy to understand and maintain.
Cheers,
Sebastian
--
Contra vim mortem non est medicamen in hortem.
|
|
|
|
|
Thanks for your advaice!
I have rebuilt it to one Thread like this:
<br />
RUNNING = true;<br />
currentRunningThreads = 0;<br />
<br />
dataCollector = new DataCollector();<br />
<br />
#region Create Connection<br />
serialPort = new SerialPort(serialPortSettings.getPort, serialPortSettings.getBoudRate, serialPortSettings.getParity, serialPortSettings.getDataBits, serialPortSettings.getStopBit);<br />
serialPort.DtrEnable = true;<br />
serialPort.RtsEnable = true;<br />
serialPort.WriteBufferSize = 102480;<br />
serialPort.ReadBufferSize = 102480;<br />
serialPort.Open();<br />
#endregion<br />
<br />
<br />
while (RUNNING)<br />
{<br />
if (serialPort.BytesToRead > 0)<br />
{<br />
onDataReceived();<br />
}<br />
else<br />
Thread.Sleep(1);<br />
}<br />
But the main part is that i have encreased the writeBuffersize but mainly the ReadBufferSize to 102480.
And with this settings i have now runned 4 stress tests that results in perfect matching files!
Proberly the reading buffert on 4048 was to small to handle the stress. This software may be runned on laptops later on, and there need to be some extra buffert for these. What do you think of the new buffert size? is it maby to big? or can i increase it more to be more safe?
Best Regards
SnowJim
|
|
|
|
|
Hi there...I need some hints how to read the list of files contained in a directory through C#.
Thanks
|
|
|
|
|
If you only need the names of the files you can call the System.IO.Direcoty.GetFiles method which returns an array of string.
If you need more information you first instatiate an DirectoryInfo object and then call the instances GetFiles method which returns an array of System.IO.FileInfo.
Sample:
<code>System.IO.DirectoryInfo windowsDir = new System.IO.DirectoryInfo(@"C:\windows\");
System.IO.FileInfo[] filesInDir = windowsDir.GetFiles("*.*");
</code>
/cadi
24 hours is not enough
|
|
|
|
|
Thanks man...It worked!
GaMBiT---> aND ReVeNGe WiLL Be
|
|
|
|
|
We have an app made in C# which promtes users for a sql query at run time, this has become difficult for the users but we were thinking of an easy to use query builder to integrate; instead of writing from scratch we were were wondering if there were available tools to use ??
|
|
|
|
|
I am making a windows form and I would like to place buttons or icons that will start other applications from the form. I am programming this is c#. I would like to know what I need to do to get the button to start other programs .exe
Thanks for any help
|
|
|
|
|
Use the System.Diagnostics.Process newProcess = System.Diagnostics.Process.Start(exe, params) method in the buttons OnClick handler.
If you need more control over the appearance of the new application you shoud first fill a ProcessStartInfo and then call the System.Diagnostics.Process newProcess = System.Diagnostics.Process.Start(startupInfo) .
To wait for the process to finish use the following code:
System.Diagnostics.Process newProcess = System.Diagnostics.Process.Start(@"c:\windows\notepad.exe");
System.Threading.WaitHandle processHandle = new System.Threading.AutoResetEvent(false);
processHandle.Handle = newProcess.Handle;
processHandle.WaitOne();
/cadi
24 hours is not enough
|
|
|
|
|
|
I translated several Windows Forms from german to english. I simply set the Localizable property in the Windows Forms Designer to true and changed the Language property to German.
But I made a mistake: The language "(Default)" now contains German texts and the language "German" contains the English texts.
Question: Is there a way to "swap" this without the need to painfully edit the .resx files by hand?
--
Affordable Windows-based CMS for only 99 €: try www.zeta-producer.com for free!
|
|
|
|
|
Public Function isChar(Expression As Variant) As Boolean
Dim str, I, length, ch
I = 1
str = Expression
length = Len(str)
While (I <= length)
ch = Mid(str, I, 1)
If Asc(ch) >= Asc("a") And Asc(ch) <= Asc("z") Or _
Asc(ch) >= Asc("A") And Asc(ch) <= Asc("Z") Or _
Asc(ch) = Asc(" ") Or Asc(ch) = Asc(".") Or _
Asc(ch) = Asc("-") Or Asc(ch) = Asc(",") Then
isChar2 = True
Else
isChar2 = False
Exit Function
End If
I = I + 1
Wend
End Function
Thanks
Monica
|
|
|
|
|
Have you even looked here?[^]
Hey don't worry, I can handle it. I took something. I can see things no one else can see. Why are you dressed like that?
- Jack Burton
|
|
|
|
|
public bool IsCharacter(string expression) {
bool success = false;
foreach(char c in expression) {
if(Char.IsDigit(c)) {
success = false;
break;
}
}
}
WM.
What about weapons of mass-construction?
|
|
|
|
|
Beside the fact your function returns nothing and wouldn't even compile (unless I add an extra return success - but in this case it always return false no matter what input you give to it), the IsDigit test is not even close to what the code of the op tested.
|
|
|
|
|
A line for line translation. Very quick and dirty, there is probably more efficent ways to do this.
public bool IsChar(string input)
{
bool isChar = true;
for(int loop = 0; loop < input.Length; loop++)
{
if((input[loop] >= 'A' && input[loop] <='Z') || (input[loop] >= 'a' && input[loop] <='z')
|| input[loop] == ' ' || input[loop] =='.'
|| input[loop] == '-' || input[loop] == ',')
{
isChar = true;
}
else
{
isChar = false;
break;
}
}
return isChar;
}
Michael
CP Blog [^] Development Blog [^]
|
|
|
|
|
I have a project where I must send data to a remote FTP server using an Active FTP connection. I'm able to connect to the remote server fine, but when I send the "POST" command, the socket is not connecting. I get the following exception error:
"A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied"
I have looked all over the net for an example of sending the FTP "POST" command, but haven't found anything. What am I doing wrong? Working examples would be greatly appreciated.
Here's the code snippet I'm trying to use (let me know if you need more information):
private string GetPortParameters(int localPort)
{
string localHost = Dns.GetHostName();
IPAddress localIPAddress = Dns.Resolve(localHost).AddressList[0];
string strLocalIPAddress = localIPAddress.ToString();
strLocalIPAddress = strLocalIPAddress.Replace('.',',');
int portParam1 = ( 0xff00 & localPort ) >> 8;
int portParam2 = ( 0xff & localPort ) ;
string portParameters = strLocalIPAddress + "," + portParam1 + "," + portParam2;
return portParameters;
}
private int GetPort()
{
if ( dataPort > 30000 )
{
dataPort = 10000;
}
return dataPort++;
}
private Socket CreateActiveDataSocket()
{
int thePort = GetPort();
string portParams = GetPortParameters(thePort);
Socket portSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
IPEndPoint ep = new IPEndPoint(Dns.Resolve(Dns.GetHostName()).AddressList[0], thePort);
portSocket.Bind(ep);
portSocket.Listen(4);
SendCommand("PORT "+portParams);
SendCommand("STOR "+Path.GetFileName("C:\\somefilename.txt"));
portSocket.Accept();
// sending the socket back to the caller to transfer (upload) the file
return portSocket;
}
Eddie
|
|
|
|
|
I've written a full featured FTP client in java, The only command to upload stuff, as far as I know, is STOR. Before sending the STOR command you will need the PORT command. The following steps need to be done:
1. Make a socket that listens on a random port (use port 0 to initialize and get the actual port after the initialisation)
2. Send the PORT command.
3. Read the response and check if it's ok
3. Send the STOR command.
4. Write the file to the socket you created.
5. Read the response of the server and check if it's ok
It should work this way
WM.
What about weapons of mass-construction?
|
|
|
|
|
Thanks for the response, WM. The problem occurs in step 4 of your post. When I try to the file to the socket I created, I get the error that I previously posted. I need to know why the connection is not being established after sending the PORT command to the server.
Eddie
|
|
|
|
|
Are you behind a firewall/proxy something like that? It seems like the server couldn't connect to your socket. Check if the response on the STOR command is 150. If it isn't the server can't connect to your listening socket.
An alternative on the port command would be the PASV command in which case you connect to the server to post your file, instead of the server connecting to you.
WM.
What about weapons of mass-construction?
|
|
|
|
|
Yes, I do get a 150 response once the STOR command is sent. I have no problem with the PASV command at all.
This is what I do for PASV (this works):
1. Connect to FTP server w/ Username/password
2. Send the PASV command and read the response from the server
3. I parse out the IP Address and Port sent by the server in step 2
4. Create a new socket with IP/Port and connect to it.
5. Send the STOR command
6. Send bytes to upload file on the connection created in step 4
This is what I assume I should be doing for PORT:
1. Connect to FTP server w/ Username/password
2. Retrieve local IP and generate random port #
3. Create new socket with IP/Port from step 2, Bind and Listen
4. Send the PORT command with the IP/Port generated in step 2 (I receive "200 Port command successful" from server)
This is where I'm unclear on what to do next. I'm assuming that the server will automatically connect to the port I just sent, but it doesn't seem to.
5. Send the STOR command (receive 150 response from server)
6. Upload file on connection that I'm listening on (Error occurs here).
The reason I'm trying to do it this way:
Our automated FTP program has been failing to send files to one of our clients in Passive mode. After we contacted them they asked that we try sending the files non-passive. What I find odd is that we receive a response from their server when sending the PASV command, but we can't connect to it. In fact, we can't even ping it. So, you might be right in that it could be a firewall issue on their end. Nevertheless, I was still tasked to get Active file transfers to work, but can't even do it on our local servers.
Any thoughts?
Thanks, Eddie
|
|
|
|