skuehner

Hello,

I am using CF 2.0.

I decided to use a SerialPort instead of a TCPClient, so I wrote a new assembly. Now all my System.Threading.Timer-Funktions don't work anymore. This only happens after opening the SerialPort. The callback is never called.

To test it I wrote my own timer-function... and it works.

I this a bug that you can't use System.Threading.Timer and SerialPort together

Thanks!


Re: .NET Compact Framework SerialPort and System.Threading.Timer

Ilya Tumanov

Please see this, items 8, 9, 10, 12.

Also I¡¯m not confident SerialPort is an adequate replacement for TCPClient as they have very different functionality. It¡¯s like replacing TV with watch or something like this. It might be adequate though if you do have a serial port (not a class - physical or virtual one) which is used to transfer data.






Re: .NET Compact Framework SerialPort and System.Threading.Timer

skuehner

Hello,

The "replace" isn't the point. The data reaches the level above.

Now I changed all my System.Threading.Timers... I do not use them anymore. Now there is a problem with some TCPServers. They don't connect. The accept-callback isn't called. So, I think that the SerialPort ist using many Threads of the Thread-Pool and there is no more space for another threads... is that right

Code Snippet

const int rxBufferSize=100;
const int txBufferSize=100;

[...]


SerialPort port = new SerialPort();
port.ReadBufferSize = rxBufferSize;
port.WriteBufferSize = txBufferSize;
port.Encoding = Encoding.UTF8;
port.ReadTimeout = 1000;
port.WriteTimeout = 1000;
port.DataReceived += new SerialDataReceivedEventHandler(receiveCallback);

port.Open();






Re: .NET Compact Framework SerialPort and System.Threading.Timer

Ilya Tumanov

I don't see any timers in this code nor I see what you're doing in callbacks. This code by itself seems to be fine but all other code you did not post can be wrong. Yes, serial port uses threads as does threading timer and asynchronous sockets. You must free up callback threads ASAP and never block them.






Re: .NET Compact Framework SerialPort and System.Threading.Timer

skuehner

Hello,

Thanks for the hint with the lock. Maybe that's wrong.

This is my callback:

private void receiveCallback(object o, SerialDataReceivedEventArgs args)
{
try
{
lock (lockReadCallbackTest)
{
int bytesRead = port.Read(session.receiveBuffer, 0, MaxBytes);
if (bytesRead >= 1)
{
session.AddDataBuffer(bytesRead);
}
}
}
catch(Exception e)
{
Manager.Error(this, "SerialBusRead", e);
}
}

I didn't know if SerialPort is Thread-Safe. AddDataBuffer is very complex, so I should do this in another thread. Isn't it

Thanks for your answer and sorry for "questioning" bad ;-)




Re: .NET Compact Framework SerialPort and System.Threading.Timer

Ilya Tumanov

Not "lock", block. "Blocking" means you doing something for a long time instead or returning right away. Yes, if AddDataBuffer() takes a long time start another thread to add data. It does not matter if SerialPort is thread safe in this case as you're not going to access it. You would read bytes from the port in the callback and then do whatever's needed with these bytes in another thread without touching serial port. Note your AddDataBuffer() must be fast enough to keep up with incoming data even if you¡¯re using separate thread for processing. In other case you would create more and more threads and at some point it would end up badly.






Re: .NET Compact Framework SerialPort and System.Threading.Timer

skuehner

Hello,

This is my new code:

Code Snippet

private void PollingThread()
{
do
{
dataReceived.WaitOne();

try
{
int bytesRead = port.Read(session.receiveBuffer, 0, MaxBytes);
if (bytesRead >= 1)
{
session.AddDataBuffer(bytesRead);
}
}
catch (Exception e)
{
Manager.Error(this, "SerialBusRead", e);
}

} while (open);
closed.Set();
}

private void receiveCallback(object o, SerialDataReceivedEventArgs args)
{
dataReceived.Set();
}



The problem: The same problem like before. When I comment port.Read (and make bytesRead=10) there is not problem, but also no data.




Re: .NET Compact Framework SerialPort and System.Threading.Timer

skuehner

It seems that there is no one who can help me...

Now I give my PollingThread the Priority "Below Normal"... and the rest of the system seems to work now (well, at least the receive callbacks of my TCPServers).

The Polling Thread is really slow now and sometimes about 2000 Bytes are to be processed after about 20 fired DataReceived-Events.




Re: .NET Compact Framework SerialPort and System.Threading.Timer

skuehner

Update:

I have to do this:

Code Snippet

Thread.CurrentThread.Priority = ThreadPriority.BelowNormal;
int bytesRead = port.Read(session.receiveBuffer, 0, MaxBytes);
Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;



... in the Polling Thread.

It would be nice to know WHY do I have to do this and accept a bad SerialBus performance.




Re: .NET Compact Framework SerialPort and System.Threading.Timer

Ilya Tumanov

It probably has nothing to do with ¡°serial bus performance¡±. It looks like you¡¯re simply overloading CPU doing something thus preventing other threads from getting any cycles. That is an indication of systematic problem in your application. You might be doing unneeded tight loops somewhere (e.g. waiting for variable to switch instead of using semaphore object) or you just might be trying to do too much (more than CPU is capable of). Allow me to repeat myself:

¡°Note your AddDataBuffer() must be fast enough to keep up with incoming data even if you¡¯re using separate thread for processing. In other case you would create more and more threads and at some point it would end up badly¡±






Re: .NET Compact Framework SerialPort and System.Threading.Timer

skuehner

Hi,

My CPU is running at 80%... changing the priorities in the PollingThread or not. It's always about 80%.

AddDataBuffer commented: 80%
port.Open() commended: 35 %

It's like 45% less when I do not open the SerialPort. :-S





Re: .NET Compact Framework SerialPort and System.Threading.Timer

Mario van Zeist

Running a CPU at 80% all the time is a dead give away to some serious performance issues. Changing thread priorities has nothing todo with that. it will merely give a thread more chance to complete its work over another (and gives other threads less chance), Having you're CPU running at 80% can also starve system threads from running. For example the system thread that's reading the serialport for you.

This has all been explained by Ilya Tumanov. What i can't understand is why you are using a pollingthread in the first place, why don't you use the DataReceived of the serial port that event will automatically fire when there is data available for you to read. no need to poll for it in a seperate thread.

BUT beware the datareceived event is executed on another thread, NOT the main UI thread, you want to complete your work in that event ASAP, and make damn sure youre not blocking that thread for too long, in short your AdddataBuffer function should complete fast. and make sure you don't change any UI elements in that thread.

As i am using SerialPorts i can tell you they should take 0% processor time, they are extremely slow compared to TCPClient (i still can't understand why you changed from TCPClient to a serialport as they serve complete different purposes), so they don't need alot of processing power.

As stated before, take a hard look at your code and see if youre not needlesly blocking threads from executing, and youre not using some tight loops to check for states in other threads changing. if you know that the code below is one of the worst threading examples ever, youre on the right track.

static bool istheredata =false;

public Init

Thread t = new Thread(Checkme)

t.Start();

while (!istheredata)

{

Donothing();

}

procedure Checkme()

{

Random r = new Random()

while(true)

{

if (r.next(100000000)==774621)

{

istheredata=true;

return;

}

}

}





Re: .NET Compact Framework SerialPort and System.Threading.Timer

skuehner

Hi!

Thanks for your help. I think this was the answer... the CPU.

When I switch off my devices sending me CANOpen data, the CPU goes down to 10%... so there is some error in my parsing or something like that. I have to make it more efficient.

Well, the reason for using a SerialPort instead of a TCPClient: My CAN-Network has a CAN->Serial Gateway. Before I had to put a Serial->TCP Adapter, too. We are changing this to CAN->UDP at this moment. So SerialBus will not be used, but I wanted to have the assembly "ready for later use".