From what I've read, beginReceive is considered superior to receive in almost all cases (or all?). This is because beginReceive is asynchronous and waits for data to arrive on a seperate thread, thereby allowing the program to complete other tasks on the main thread while waiting.
But with beginReceive, the callback function still runs on the main thread. And so there is overhead with switching back and forth between the worker thread and the main thread each time data is received. I know the overhead is small, but why not avoid it by simply using a separate thread to host a continuous loop of receive calls?
Can someone explain to me what is inferior about programming with the following style:
static void Main()
{
double current_temperature = 0; //variable to hold data received from server
Thread t = new Thread (UpdateData);
t.start();
// other code down here that will occasionally do something with current_temperature
// e.g. send to a GUI when button pressed
... more code here
}
static void UpdateData()
{
Socket my_socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
my_socket.Connect (server_endpoint);
byte [] buffer = new byte[1024];
while (true)
my_socket.Receive (buffer); //will receive data 50-100 times per second
// code here to take the data in buffer
// and use it to update current_temperature
... more code here
end
}
Related
I'm new to multi-threading and I'm to understand how the AutoResetEvent works.
I'm trying to implement an optimization process where I'm sending data between two different softwares and I'm using two threads: the Main thread where I'm modifying and sending information and a Receiving Thread, always running in the background, waiting to catch the message with the results from the Sent Info. To implement that, after a message is sent, I want the main thread to wait until the receiver thread receives back the result and triggers the event that allows the main thread to continue where it left off.
Here is a simplified version of my code:
// Thread 1 - MAIN
static AutoResetEvent waitHandle = new AutoResetEvent(false);
void foo()
{
for (int i = 0; i < 5; i++)
{
// ... Modify sendInfo data
// Send data to other software
SendData(sendInfo);
// Wait for other software to process data and send back the result
waitHandle.WaitOne();
// Print Result
print(receivedData);
// Reset AutoResetEvent
waitHandle.Reset();
}
}
/////////////////////////////
// Thread 2 - Receiver thread (running in the background)
private event EventHandler MessageReceived;
// ... Code for triggerring MessageReceived event each time a message is received
private static void OnMessageReceived(object sender, EventArgs e)
{
waitHandle.Set();
}
My question is:
Can you repeatedly use an AutoResetEvent in a loop like this? Am I using it correctly?
I'm pretty sure my send/receive loop is working properly, with the MessageReceived event succesfully triggered shortly after the sent message. But while my code works fine for a single iteration, it gets stuck on multiple iterations and I'm not sure why. Any suggestions?
I'm currently working on a program's subsystem that requires writing data to disk. I've implemented this as a multithreaded Producer-Consumer model that generates packets of data in one thread, puts them in a queue and writes them to disk in another thread.
The program has to use minimal CPU resources, so to avoid the write thread idling while it is waiting for a packet of data to arrive, I extended the ConcurrentQueue class to trigger an Event when a packet has been added to the queue, so that the write function is only active when there is data available. Here's the generate function:
while (writeData)
{
for (int i = 0; i < packetLength; i++)
{
packet.data[i] = genData();
}
packet.num++;
// send packet to queue to be written
// this automatically triggers an Event
queue.Enqueue(packet);
}
My problem is that I haven't been able to figure out how to assign the Event Handler (ie: the write operation) to a seperate thread - as far as I'm aware, Event Handlers in C# are run on the same thread that triggered the event.
I've thought about using the ThreadPool, but I'm unsure as to whether the packets in the queue would be written sequentially or in parallel. Writing packets in parallel would not work in this context, as they are all being written to the same file and have to be written in the order they arrive in. This is what I have so far:
private void writeEventCatch(object sender, EventArgs e)
{
// catch event and queue a write operation
ThreadPool.QueueUserWorkItem(writeToDisk);
}
private void writeToDisk(Object stateInfo)
{
// this is a struct representing the packet
nonCompBinData_P packet;
while (queue.TryDequeue(out packet))
{
// write packet to stream
serialiser.Serialize(fileStream, packet);
packetsWritten++;
}
}
while (queue.TryDequeue(out packet)) will quit as long as there are no packets to dequeue. what you need to do is start single thread for writing operation deque work items and write data to disk. items will be dequeued one by one and in order they arrive.
To begin with, I'm using unity. Which makes me stuck with .NET 3.5. I'm currently working on a server program which uses the Socket object's asynchronous methods (E.G. BeginReceive, BeginAccept, BeginReceiveFrom etc.). When the server receives a packet from a client, this packet is received on a worker thread. Now I'm left with some data on a worker thread, and I want the main thread to process this data using a function that I specify. I implemented that:
using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
public class MyDispatcherClass
{
public delegate void MyDel();
private readonly Queue<MyDel> commands = new Queue<MyDel>();
Object lockObj = new object ();
public void Add(MyDel dc)
{
lock (lockObj)
{
commands.Enqueue (dc);
}
}
public void Invoke()
{
lock (lockObj)
{
while (commands.Count > 0)
{
commands.Dequeue().Invoke();
}
}
}
}
Then I would use it this way:
// As a global variable:
MyDispatcherClass SomeDispatcher = new MyDispatcherClass ();
//The function that I want to call:
public void MyFunction (byte[] data)
{
// Do some stuff on the main thread
}
//When I receive a message on a worker thread I do that:
SomeDispatcher.Add (()=> MyFunction (byte[] data)); //Asuume that "data" is the message I received from a client
//Each frame on the main thread I call:
SomeDispatcher.Invoke ();
After some research, I found that the lock statement does not guarantee a %100 FIFO implementation. Which is not what I wanted, sometimes this may cause a total server breakdown! I want to achieve the same result with a %100 guarantee that data will be processed in the same order it was received from a client. How could I accomplish that?
Threads will run in whatever order they want, so you can't force the order going into the queue. But you can put in more data into the queue than just what you will eventually be processing.
If you add a DateTime, (or even just an int with a specified order) to the data being sent you can sort your queue on that when you pull data from it, (and possibly not pull any data less than 0.5 seconds old to give time for other threads to write their data.)
Normally when dealing with client-server relationships each thread represents one client so you don't have to worry about this as commands are FIFO within the thread, (although they might not be when 2 different clients are sending messages.)
Do you close and re-open the socket on the same client? that could make it use different threads. If you need a specific order and are sending things fairly soon after each other it might be better to leave the socket open.
I am writing a program to simulate a device that transmits data over the serial port. To do this, I created a System.IO.Ports.SerialPort object in my form, and a System.Windows.Forms.Timer to do the transmitting at a given frequency. Everything works fine except that as the frequency approaches the limit of the serial port speed, it starts to lock up the UI and eventually becomes unresponsive when the data is being sent for transmission faster than the port data speed. My code is:
private void OnSendTimerTick(object sender, EventArgs e)
{
StringBuilder outputString = new StringBuilder("$", 51);
//code to build the first output string
SendingPort.WriteLine(outputString.ToString());
outputString = new StringBuilder("$", 44);
//code to build the second output string
SendingPort.WriteLine(outputString.ToString());
if (SendingPort.BytesToWrite > 100)
{
OnStartStopClicked(sender, e);
MessageBox.Show("Warning: Sending buffer is overflowing!");
}
}
I was expecting the WriteLine function to be asynchronous - return immediately while the port transmits in the background. Instead, it seems that the OnSendTimerTick function is properly threaded, but WriteLine seems to be running in the UI thread.
How can I get the serial port to behave in this way? Creating the SerialPort object in the timer seems like a bad idea, because then I'd have to open and close it on each timer tick.
It is only partly asynchronous, it will immediately return but only as long as the bytes you write will fit in the serial port driver's transmit buffer. That's going to come to a screeching stop when you flood the port with too much data, faster than it can transmit. You can make it truly asynchronous by using the SerialPort.BaseStream.BeginWrite() method. That doesn't make it any faster but moves the bottleneck somewhere else, possibly away from the UI.
If you're using System.Windows.Forms.Timer, the timer event handler is being executed on the UI thread. Same is true if you're using System.Timers.Timer when the SynchronizingObject is set to the form. If the serial port buffer fills up, the thread has to wait until it has enough space to hold the new data that you want to send.
I would suggest that you use a System.Threading.Timer to do this. The timer callback is called on a pool thread, meaning that the UI thread won't lock up if the WriteLine has to wait. If you do this, then you have to make sure that there is only one threading executing the timer callback at any time. Otherwise you can get data out of order. The best way to do that would be to make the timer a one-shot and re-initialize it at the end of every callback:
const int TimerFrequency = 50; // or whatever
System.Threading.Timer timer;
void InitTimer()
{
timer = new System.Threading.Timer(TimerCallback, null, TimerFrequency, Timeout.Infinite);
}
void TimerCallback(object state)
{
// do your stuff here
// Now reset the timer
timer.Change(TimerFrequency, Timeout.Infinite);
}
Passing a valid of Timeout.Infinite as the period parameter prevents the timer from being a periodic timer. Instead, it fires just once. The Timer.Change re-initializes the timer after each send.
A possibly better way to handle this is to eliminate the timer altogether by setting the WriteBufferSize to a sufficiently large value. Then your program can just dump all of its data into the buffer and let the SerialPort instance worry about dribbling it out across the wire. This assumes, of course, that you can create a buffer large enough to hold whatever your program is trying to send.
This could be resolved(slowness of the UI) if you created a Queue of strings to be written and had a background thread that wrote to the serial port from the queue. If you take that approach be careful of the size of the queue.
edit: For some reason I can't use Add Comment, so I'll just edit this. The documentation for BeginWrite has this statement "The default implementation of BeginWrite on a stream calls the Write method synchronously, which means that Write might block on some streams." It then goes on to exclude File and Network streams, but not SerialPort. I guess you can try it and see.
I am using the TcpClient class in C#.
Each time there is a new tcp connection request, the usual practice is to create a new thread to handle it. And it should be possible for the main thread to terminate these handler threads anytime.
My solution for each of these handler thread is as follows:
1 Check NetworkStream's DataAvailable method
1.1 If new data available then read and process new data
1.2 If end of stream then self terminate
2 Check for terminate signal from main thread
2.1 If terminate signal activated then self terminate
3 Goto 1.
The problem with this polling approach is that all of these handler threads will be taking up significant processor resources and especially so if there is a huge number of these threads. This makes it highly inefficient.
Is there a better way of doing this?
See Asynchronous Server Socket Example to learn how to do this the ".NET way", without creating new threads for each request.
Believe it or not that 1000 tick sleep will really keep things running smooth.
private readonly Queue<Socket> sockets = new Queue<Socket>();
private readonly object locker = new object();
private readonly TimeSpan sleepTimeSpan = new TimeSpan(1000);
private volatile Boolean terminate;
private void HandleRequests()
{
Socket socket = null;
while (!terminate)
{
lock (locker)
{
socket = null;
if (sockets.Count > 0)
{
socket = sockets.Dequeue();
}
}
if (socket != null)
{
// process
}
Thread.Sleep(sleepTimeSpan);
}
}
I remember working on a similar kind of Windows Service. It was a NTRIP Server that can take around 1000 TCP connections and route the data to a NTRIP Caster.
If you have a dedicated server for this application then it will not be a problem unless you add more code to each thread (File IO, Database etc - although in my case I also had Database processing to log the in/out for each connection).
The things to watch out for:
Bandwidth when the threads goes up to 600 or so. You will start seeing disconnections when the TCP Buffer window is choked for some reason or the available bandwidth falls short
The operating system on which you are running this application might have some restrictions, which can cause disconnections
The above might not be applicable in your case but I just wanted it put it here because I faced then during development.
You're right that you do not want all of your threads "busy waiting" (i.e. running a small loop over and over). You either want them blocking, or you want to use asynchronous I/O.
As John Saunders mentioned, asynchronous I/O is the "right way" to do this, since it can scale up to hundreds of connections. Basically, you call BeginRead() and pass it a callback function. BeginRead() returns immediately, and when data arrives, the callback function is invoked on a thread from the thread pool. The callback function processes the data, calls BeginRead() again, and then returns, which releases the thread back into the pool.
However, if you'll only be holding a handful of connections open at a time, it's perfectly fine to create a thread for each connection. Instead of checking the DataAvailable property in a loop, go ahead and call Read(). The thread will block, consuming no CPU, until data is available to read. If the connection is lost, or you close it from another thread, the Read() call will throw an exception, which you can handle by terminating your reader thread.