will a call to SQL cause my multi threading app to bottleneck? - c#

will the call to SQL in my multi threaded application cause the app to be bottleneck?
Is the logic i am using valid and conform to best practice?
static void Main(string[] args)
{
try
{
TcpListener listener = new TcpListener(IPAddress.Any, 8000);
TcpClient client;
listener.Start();
while (true) // Add your exit flag here
{
client = listener.AcceptTcpClient();
ThreadPool.QueueUserWorkItem(ThreadProc, client);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}//Main
private static void ThreadProc(object obj)
{
var client = (TcpClient)obj;
// Do your work here...
NetworkStream ns = client.GetStream();
using (StreamWriter writer = new StreamWriter(ns))
{
writer.WriteLine("220 SMTP server ready.");
writer.Flush();
using (StreamReader reader = new StreamReader(ns))
{
//parse + persist smtp message here...
//save email message parts to a Email table in SQL SVR(from, to, body...)
}
}
}//ThreadProc

The way I would approach this is to have a Queue which you add the stuff you're going to parse and persist and then have that serviced by a pool of threads, or even just one thread, it depends on the expected throughput. The key here is the queue is serviced as soon as possible, but if there is a backlog it doesn't affect adding more items.
Edit:
There are a bunch of unknowns in your scenario, so my solution was equally vague, but I should of explained that.
The problem with your problem is I don't know how long your sql will run, or what action should be taken if it fails/times out, or how many of these sql statements you're expecting to queue up or run.
My solution would be to first extract the public facing interface for a) queuing an operation and b) processing an operation. this gives you the opportunity to, at a later date, or even now, switch out the queuing mechanism for something more appropriate.
So, take the case where by you are queuing work items, and the database stops responding. Suddenly nothing is being saved. Does that affect what your application does? Is there any sort of transactional issue here? Would it be better perhaps to be writing the work item to something like MSMQ? SQL Server also has a broker service which could be pretty spot on for what you want.
So I'm not going to add any code, but think in these terms:
1) Specify interfaces interface:
public interface QueueWorkItem
{
void AddWorkItemToQueue(WorkItem item);
}
public interface ConsumeWorkItem
{
bool ItemsInQueue {get;}
WorkItem GetNextItem();
}
You don't have to use these, it's just examples.
2) Build a class that implements the interfaces
This is the fun bit, you have to worry about threading and blocking (Look for producer consumer pattern) You could always use the threadpool and have the ConsumeWorkItem do nothing really.
Finally, lets talk about the threadpool. It's fine, but you don't have much control over it, and there's no guarantee that all the threads running in it are yours.
Hope that helps.

Related

Correct way of managing threads

I'm building a C# Socket Server. My code currently works but I am not sure if this is the correct way to do it.
When a TcpClient is connected I put it in a new object with the following Methods, I then call Init() to start checking if data is available, when data is available I call an event that I listen on to start reading the buffer using methods I created like ReadInt32(), ReadByte(), ReadString() ReadObject<T>()
public void Init()
{
ThreadPool.QueueUserWorkItem(Read);
}
private void Read(object state)
{
if (IsClientConnected())
{
if (_connected.Available > 0)
{
OnDataAvailable(_connected.Available);
}
Init();
}
}
Should I use a While loop here or should I restart the Init() like I am currently doing? Then should I use a BackgroundWorker, Thread, or Task instead of ThreadPool?
I also was thinking of changing Init() to BeginWait(some sort of callback here) and removing the Init() inside the Read() and then just call BeginWait again where needed
My purpose is to listen to commands and reply on commands. With an x number of clients connected at the same time.
So the scenario is as follow:
I have an application that connects to the server.
The server then Initializes a new object with TcpClient as a parameter in the constructor. The server then adds the connected client to a room with another client. This room listens on each of the client's events DataAvailable look at following
private void Client_DataAvailable(ClientWrapper sender, int data)
{
var command = (Commands)Client.ReadByte();
switch (command)
{
case Commands.RequestConnectId: // 1
var buffer = new WriteBuffer(Commands.RequestConnectId);
buffer.WriteInt32(sender.ConnectId);
sender.Reply(buffer);
break;
case Commands.WriteText: //2
var buffer = new WriteBuffer(Commands.WriteText);
buffer.WriteString(sender.ReadString());
BroadCast(sender.ConnectId,buffer);//Send to the other client
break;
}
}
The correct way to read a socket is to just read from it. The call will not complete until data is ready. There is no need for events. The Available property almost always is a bug so don't use that.
Just execute:
var command = (Commands)Client.ReadByte();
immediately. It is fine to run that on a background thread (as opposed to what was suggested in the comments). Threads become a problem once you have too many of them. If you maintain a few dozen socket connections only there is no issue with that.
You also could use async IO preferably with await. The same idea applies: Just read.
If you want to process a stream of command simply wrap this in a loop:
while (true) {
ReadCommand();
WriteResponse();
}

Rabbit MQ - Recovery of connection/channel/consumer

I am creating a consumer that runs in an infinite loop to read messages from the queue. I am looking for advice/sample code on how to recover abd continue within my infinite loop even if there are network disruptions. The consumer has to stay running as it will be installed as a WindowsService.
1) Can someone please explain how to properly use these settings? What is the difference between them?
NetworkRecoveryInterval
AutomaticRecoveryEnabled
RequestedHeartbeat
2) Please see my current sample code for the consumer. I am using the .Net RabbitMQ Client v3.5.6.
How will the above settings do the "recovery" for me?
e.g. will consumer.Queue.Dequeue block until it is recovered?
That doesn't seem right
so...
Do I have to code for this manually? e.g. will consumer.Queue.Dequeue throw an exception for which I have to detect and manually re-create my connection, channel, and consumer? Or just the consumer, as "AutomaticRecovery" will recover the channel for me?
Does this mean I should move the consumer creation inside the while loop? what about the channel creation? and the connection creation?
3) Assuming I have to do some of this recovery code manually, are there event callbacks (and how do I register for them) to tell me that there are network problems?
Thanks!
public void StartConsumer(string queue)
{
using (IModel channel = this.Connection.CreateModel())
{
var consumer = new QueueingBasicConsumer(channel);
const bool noAck = false;
channel.BasicConsume(queue, noAck, consumer);
// do I need these conditions? or should I just do while(true)???
while (channel.IsOpen &&
Connection.IsOpen &&
consumer.IsRunning)
{
try
{
BasicDeliverEventArgs item;
if (consumer.Queue.Dequeue(Timeout, out item))
{
string message = System.Text.Encoding.UTF8.GetString(item.Body);
DoSomethingMethod(message);
channel.BasicAck(item.DeliveryTag, false);
}
}
catch (EndOfStreamException ex)
{
// this is likely due to some connection issue -- what am I to do?
}
catch (Exception ex)
{
// should never happen, but lets say my DoSomethingMethod(message); throws an exception
// presumably, I'll just log the error and keep on going
}
}
}
}
public IConnection Connection
{
get
{
if (_connection == null) // _connection defined in class -- private static IConnection _connection;
{
_connection = CreateConnection();
}
return _connection;
}
}
private IConnection CreateConnection()
{
ConnectionFactory factory = new ConnectionFactory()
{
HostName = "RabbitMqHostName",
UserName = "RabbitMqUserName",
Password = "RabbitMqPassword",
};
// why do we need to set this explicitly? shouldn't this be the default?
factory.AutomaticRecoveryEnabled = true;
// what is a good value to use?
factory.NetworkRecoveryInterval = TimeSpan.FromSeconds(5);
// what is a good value to use? How is this different from NetworkRecoveryInterval?
factory.RequestedHeartbeat = 5;
IConnection connection = factory.CreateConnection();
return connection;
}
RabbitMQ features
The documentation on RabbitMQ's site is actually really good. If you want to recover queues, exchanges and consumers, you're looking for topology recovery, which is enabled by default. Automatic Recovery (which is enabled by default) includes:
Reconnect
Restore connection listeners
Re-open channels
Restore channel listeners
Restore channel basic.qos setting, publisher confirms and transaction settings
The NetworkRecoveryInterval is the amount of time before a retry on an automatic recovery is performed (defaults to 5s).
Heartbeat has another purpose, namely to identify dead TCP connections. There are more to read about that at RabbitMQ's site.
Code sample
Writing reliable code for recovery is tricky. The EndOfStreamException is (as you suspect) most likely due to network problems. If you use the management plugin, you can reproduce this by closing the connection from there and see that the exception is triggered. For production-like applications, you might want to have a set of brokers that you alternate between in case of connection failure. If you have several RabbitMQ brokers, you might also want to guard yourself against long-term server failure on one or more of the servers. You might want to implement error strategies, like requeuing the message, or using a dead letter exchange.
I've been thinking a bit of these things and written a thin client, RawRabbit, that handles some of these things. Maybe it could be something for you? If not, I would suggest that you change the QueueingBasicConsumer to an EventingBasicConsumer. It is event driven, rather than thread blocking.
var eventConsumer = new EventingBasicConsumer(channel);
eventConsumer.Received += (sender, args) =>
{
var body = args.Body;
eventConsumer.Model.BasicAck(args.DeliveryTag, false);
};
channel.BasicConsume(queue, false, eventConsumer);
If you have topology recovery activated, the consumer will be restored by the RabbitMQ Client and start receiving messages again.
For more granular control, hook up event handlers for ConsumerCancelled and Shutdown to detect connectivity problems and Registered to know when the consumer can be used again.

Can a TCP c# client receive and send continuously/consecutively without sleep?

This is to a degree a "basics of TCP" question, yet at the same time I have yet to find a convincing answer elsewhere and believe i have a ok/good understanding of the basics of TCP. I am not sure if the combination of questions (or the one questions and while i'm at it the request for confirmation of a couple of points) is against the rules. Hope not.
I am trying to write a C# implementation of a TCP client, that communicates with an existing app containing a TCP server (I don't have access to its code, so no WCF). How do I connect to it, send and receive as needed as new info comes in or out, and ultimately disconnect. Using the following MSDN code as an example where they list "Send" and "Receive" asynchronous methods (or just TcpClient), and ignoring the connect and disconnect as trivial, how can I best go about continuously checking for new packets received and at the same time send when needed?
I initially used TCPClient and GetStream(), and the msdn code still seems to require the loop and sleep described in a bit (counter intuitively), where I run the receive method in a loop in a separate thread with a sleep(10) milliseconds, and Send in the main (or third) thread as needed. This allows me to send fine, and the receive method effectively polls at regular intervals to find new packets. The received packets are then added to a queue.
Is this really the best solution? Shouldn't there be a DataAvailable event equivalent (or something i'm missing in the msdn code) that allows us to receive when, and only when, there is new data available?
As an afterthought I noticed that the socket could be cut from the other side without the client becoming aware till the next botched send. To clarify then, the client is obliged to send regular keepalives (and receive isn't sufficient, only send) to determine if the socket is still alive. And the frequency of the keepalive determines how soon I will know that link is down. Is that correct? I tried Poll, socket.connected etc only to discover why each just doesn't help.
Lastly, to confirm (i believe not but good to make sure), in the above scenario of sending on demand and receiving if tcpclient.DataAvailable every ten seconds, can there be data loss if sending and receiving at the same time? If at the same time I am receiving I try and send will one fail, overwrite the other or any other such unwanted behaviour?
There's nothing wrong necessarily with grouping questions together, but it does make answering the question more challenging... :)
The MSDN article you linked shows how to do a one-and-done TCP communication, that is, one send and one receive. You'll also notice it uses the Socket class directly where most people, including myself, will suggest using the TcpClient class instead. You can always get the underlying Socket via the Client property should you need to configure a certain socket for example (e.g., SetSocketOption()).
The other aspect about the example to note is that while it uses threads to execute the AsyncCallback delegates for both BeginSend() and BeginReceive(), it is essentially a single-threaded example because of how the ManualResetEvent objects are used. For repeated exchange between a client and server, this is not what you want.
Alright, so you want to use TcpClient. Connecting to the server (e.g., TcpListener) should be straightforward - use Connect() if you want a blocking operation or BeginConnect() if you want a non-blocking operation. Once the connection is establish, use the GetStream() method to get the NetworkStream object to use for reading and writing. Use the Read()/Write() operations for blocking I/O and the BeginRead()/BeginWrite() operations for non-blocking I/O. Note that the BeginRead() and BeginWrite() use the same AsyncCallback mechanism employed by the BeginReceive() and BeginSend() methods of the Socket class.
One of the key things to note at this point is this little blurb in the MSDN documentation for NetworkStream:
Read and write operations can be performed simultaneously on an
instance of the NetworkStream class without the need for
synchronization. As long as there is one unique thread for the write
operations and one unique thread for the read operations, there will
be no cross-interference between read and write threads and no
synchronization is required.
In short, because you plan to read and write from the same TcpClient instance, you'll need two threads for doing this. Using separate threads will ensure that no data is lost while receiving data at the same time someone is trying to send. The way I've approached this in my projects is to create a top-level object, say Client, that wraps the TcpClient and its underlying NetworkStream. This class also creates and manages two Thread objects, passing the NetworkStream object to each during construction. The first thread is the Sender thread. Anyone wanting to send data does so via a public SendData() method on the Client, which routes the data to the Sender for transmission. The second thread is the Receiver thread. This thread publishes all received data to interested parties via a public event exposed by the Client. It looks something like this:
Client.cs
public sealed partial class Client : IDisposable
{
// Called by producers to send data over the socket.
public void SendData(byte[] data)
{
_sender.SendData(data);
}
// Consumers register to receive data.
public event EventHandler<DataReceivedEventArgs> DataReceived;
public Client()
{
_client = new TcpClient(...);
_stream = _client.GetStream();
_receiver = new Receiver(_stream);
_sender = new Sender(_stream);
_receiver.DataReceived += OnDataReceived;
}
private void OnDataReceived(object sender, DataReceivedEventArgs e)
{
var handler = DataReceived;
if (handler != null) DataReceived(this, e); // re-raise event
}
private TcpClient _client;
private NetworkStream _stream;
private Receiver _receiver;
private Sender _sender;
}
Client.Receiver.cs
private sealed partial class Client
{
private sealed class Receiver
{
internal event EventHandler<DataReceivedEventArgs> DataReceived;
internal Receiver(NetworkStream stream)
{
_stream = stream;
_thread = new Thread(Run);
_thread.Start();
}
private void Run()
{
// main thread loop for receiving data...
}
private NetworkStream _stream;
private Thread _thread;
}
}
Client.Sender.cs
private sealed partial class Client
{
private sealed class Sender
{
internal void SendData(byte[] data)
{
// transition the data to the thread and send it...
}
internal Sender(NetworkStream stream)
{
_stream = stream;
_thread = new Thread(Run);
_thread.Start();
}
private void Run()
{
// main thread loop for sending data...
}
private NetworkStream _stream;
private Thread _thread;
}
}
Notice that these are three separate .cs files but define different aspects of the same Client class. I use the Visual Studio trick described here to nest the respective Receiver and Sender files under the Client file. In a nutshell, that's the way I do it.
Regarding the NetworkStream.DataAvailable/Thread.Sleep() question. I would agree that an event would be nice, but you can effectively achieve this by using the Read() method in combination with an infinite ReadTimeout. This will have no adverse impact on the rest of your application (e.g., UI) since it's running in its own thread. However, this complicates shutting down the thread (e.g., when the application closes), so you'd probably want to use something more reasonable, say 10 milliseconds. But then you're back to polling, which is what we're trying to avoid in the first place. Here's how I do it, with comments for explanation:
private sealed class Receiver
{
private void Run()
{
try
{
// ShutdownEvent is a ManualResetEvent signaled by
// Client when its time to close the socket.
while (!ShutdownEvent.WaitOne(0))
{
try
{
// We could use the ReadTimeout property and let Read()
// block. However, if no data is received prior to the
// timeout period expiring, an IOException occurs.
// While this can be handled, it leads to problems when
// debugging if we are wanting to break when exceptions
// are thrown (unless we explicitly ignore IOException,
// which I always forget to do).
if (!_stream.DataAvailable)
{
// Give up the remaining time slice.
Thread.Sleep(1);
}
else if (_stream.Read(_data, 0, _data.Length) > 0)
{
// Raise the DataReceived event w/ data...
}
else
{
// The connection has closed gracefully, so stop the
// thread.
ShutdownEvent.Set();
}
}
catch (IOException ex)
{
// Handle the exception...
}
}
}
catch (Exception ex)
{
// Handle the exception...
}
finally
{
_stream.Close();
}
}
}
As far as 'keepalives' are concerned, there is unfortunately not a way around the problem of knowing when the other side has exited the connection silently except to try sending some data. In my case, since I control both the sending and receiving sides, I've added a tiny KeepAlive message (8 bytes) to my protocol. This is sent every five seconds from both sides of the TCP connection unless other data is already being sent.
I think I've addressed all the facets that you touched on. I hope you find this helpful.

Thread and TcpListener in C#

I need to write some code that uses TcpListener. The object that using the TcpListener has 3 possibilities: Listen, Stop Listen, Send message. This is how my code looks:
public class someClass
{
public bool listenerEnable {get; set; }
public void StartListen()
{
.
.
.
while (listenerEnable)
{
// Block until client connected
TcpClient client = server.AcceptTcpClient();
// code that doing something with the client message ...
}
}
}
Now, I'm not sure I know how I can keep the thread safe when I want to stop the listener state (change the listenerEnable to be false).
Also I'm not sure I know how to keep this thread safe when I want to send some message to the client (in some separated method) without stopping the server listener state.
Thanks for any help.
I would suggest waiting on an event rather than waiting on a variable. In your current scheme, consider the case when your loop test for whether listener variable is true. If it is it enters the loop and waits for a incoming connection, and blocks. So now even if another thread sets the listener variable to be false, your loop will not exit till someone connects to it and it processes that connection.
One way of working around the problem above will be to have code like:
WaitHandle[] waitHandles = new WaitHandle[] {endlLoopEvent};
while(true)
{
int ret = WaitHandle.WaitAny(waitHandles, 100);
if(WaitTimeout == ret) continue;
else if(0 == ret) break; //our event has been signaled.
else
{
if(!server.Pending()) continue; //Go back to the loop if no connection pending
TcpClient client = server.AcceptTcpClient();
// You can spawn a thread to service the request.
}
}
Sending would not affect the loop above, provided it is not in response to a request for connection above.
Writing a correct, scalable socket server is not simple - I suggest you find / buy one - this has been done many times before.
To answer your question, your problem is that AcceptTcpClient is a blocking call. You will want to use the APM ( Asyncronous Programming Model ) methods that start with BeginXXX and EndXXXlike MSDN BeginAcceptTcpClient.
These methods don't block threads, but you will have to handle the concurrency.

How do I get an asynchronous TCP object stream in C#?

I'm pretty new to serialization so please bear with me.
I want two instances of my application to communicate with each other over the internet. I have successfully rigged up a TCP client/server relationship and used a binary formatter to get the two sides to swap a single pair of messages. Here's the client side...
using (TcpClient clientSocket = new TcpClient(ipAddress, currentPort))
{
using (NetworkStream stream = clientSocket.GetStream())
{
// send
bformatter.Serialize(stream, new Message());
// recv
return (Message)bformatter.Deserialize(stream);
}
}
It's cool, but not very useful for an application that needs to send messages in response to user events. So I need to be able to send and receive asynchronously.
I basically want an interface that behaves like this:
class BidirectionalObjectStream
{
public BidirectionalObjectStream(TcpClient client)
{
//...
}
// objects go in here
public void SendObject(object o)
{
//...
}
// objects come out here
public event Action<object> ObjectReceived;
}
Is there a class like this that's part of .NET? If not, how should I implement the receive event? Maybe a dedicated thread calling bformatter.Deserialize() repeatedly...?
Any help appreciated.
The question is a little broad.
I can think of two options:
Use asynchronous socket. Using an Asynchronous Client Socket
Create separate threads for receiving and sending. There many ways to achieve it, raw Thread, ThreadPool, delegate.Invoke, new TPL features like Task and Parallel.

Categories