While attempting to send a message for a queue through the BeginSend call seem te behave as a blocking call.
Specificly I have:
public void Send(MyMessage message)
{
lock(SEND_LOCK){
var state = ...
try {
log.Info("Begin Sending...");
socket.BeginSend(message.AsBytes(),0, message.ByteLength, SocketFlags.None,
(r) => EndSend(r), state);
log.Info("Begin Send Complete.");
}
catch (SocketException e) {
...
}
}
}
The callback would be something like this:
private void EndSend(IAsyncResult result) {
log.Info("EndSend: Ending send.");
var state = (MySendState) result.AsyncState;
...
state.Socket.EndSend(result, out code);
log.Info("EndSend: Send ended.");
WaitUntilNewMessageInQueue();
SendNextMessage();
}
Most of the time this works fine, but sometimes it hangs. Logging indicates this happens when BeginSend en EndSend are excecuted on the same Thread. The WaitUntilNewMessageInQueue blocks until there is a new message in the queue, so when there is no new message it can wait quit a while.
As far as I can tell this should not really be a problem, but in the some cases BeginSend blocks causing a deadlock situation where EndSend is blocking on WaitUntilNewMessageInQueue (expected), but Send is blocking on BeginSend in return as it seems te be waiting for the EndSend callback te return (not expected).
This behaviour was not what I was expecting. Why does BeginSend sometimes block if the callback does not return in timely fashion?
First of all, why are you locking in your Send method? The lock will be released before the send is complete since you are using BeginSend. The result is that multiple sends can be executing at the same time.
Secondly, do not write (r) => EndSend(r), just write EndSend (without any parameters).
Thrid: You do not need to include the socket in your state. Your EndSend method is working like any other instance method. You can therefore access the socket field directly.
As for your deadlocks, it's hard to tell. You delegate may have something to do with it (optimizations by the compiler / runner). But I have no knowledge in that area.
Need more help? Post more code. but I suggest that you fix the issues above (all four of them) and try again first.
Which operating system are you running on?
Are you sure you're seeing what you think you're seeing?
The notes on the MSDN page say that Send() CAN block if there's no OS buffer space to initiate your async send unless you have put the socket in non blocking mode. Could that be the case? Are you potentially sending data very quickly and filling the TCP window to the peer? If you break into the debugger what does the call stack show?
The rest is speculation based on my understanding of the underlying native technologies involved...
The notes for Send() are likely wrong about I/O being cancelled if the thread exits, this almost certainly depends on the underlying OS as it's a low level IO Completion Port/overlapped I/O issue that changed with Windows Vista (see here: http://www.lenholgate.com/blog/2008/02/major-vista-overlapped-io-change.html) and given that they're wrong about that then they could be wrong about how the completions (calls to EndSend() are dispatched on later operating systems). From Vista onwards it's possible that the completions could be dispatched on the issuing thread if the .Net sockets wrapper is enabling the correct options on the socket (see here where I talk about FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)... However, if this were the case then it's likely that you'd see this behaviour a lot as initially most sends are likely to complete 'in line' and so you'd see most completions happening on the same thread - I'm pretty sure that this is NOT the case and that .Net does NOT enable this option without asking...
This is how you check if it completed synchronously so you avoid the callback on another thread.
For a single send:
var result = socket.BeginSend(...);
if (result.CompletedSynchronously)
{
socket.EndSend(result);
}
For a queue of multiple sends, you can just loop and finalize all synchronous sends:
while (true)
{
var result = socket.BeginSend(...);
if (!result.CompletedSynchronously)
{
break;
}
socket.EndSend(result);
}
Related
I am using NetworkStream with TcpClient.
First I setup my tcp client:
tcp = new TcpClient(AddressFamily.InterNetwork)
{ NoDelay = true, ReceiveTimeout = 5000};
My main data-receiving loop:
while (true)
{
//read available data from the device
int numBytesRead = await ReadAsync();
Console.WriteLine($"{numBytesRead} bytes read"); //BP2
}
And the actual TCP data reading:
public Task<int> ReadAsync()
{
var stream = tcp.GetStream();
return stream.ReadAsync(InBuffer, 0, InBuffer.Length); //BP1
}
I have this connected to a testbed which lets me send manual packets. Through setting breakpoints and debugging I have checked that stream.ReadTimeout takes the value 5000 from tcp.
If I send data frequently it all works as expected. But if I don't send any data, nothing appears to happen after 5s, no timeout. I see breakpoint BP1 being hit in the debugger but until I send data from my testbed, BP2 is not hit. I can leave it a minute or more and it just seems to sit waiting, but receives data sent after a minute, which appears to be incorrect behavior. After 5 seconds something should happen, surely (an exception as I understand it)?
It's late so I am expecting something really basic but can anyone see what my mistake is and a resolution?
Addendum
OK so when I RTFM for the actual .Net version I'm using (how may times have I been caught out by MS defaulting to .Net Core 3, I did say it was late) I see in the remarks sectio for ReadTimeout:
This property affects only synchronous reads performed by calling the
Read method. This property does not affect asynchronous reads
performed by calling the BeginRead method.
I'm unclear now if I can use modern awaitable calls at all to read socket data safely and with a timeout specifically. It's working except for the timeout but I'm not sure how given ReadAsync has no override in NetworkStream. Must I do some ugly hack or is there a simple solution?
In my case 5000 is the longest I can expect not to receive data before concluding there is a problem - the protocol has no ping mechanism so if nothing appears I assume the connection is dead. Hence thinking an Async read with a 5000ms timeout would be nice and neat.
Timeout values for network objects apply only to synchronous operations. For example, from the documentation:
This option applies to synchronous Receive calls only.
For Socket.ReceiveTimeout, TcpClient.ReceiveTimeout, and NetworkStream.ReadTimeout, the implementations all ultimately result in a call to SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, ...) which in turn is effectively calling the native setsockopt() function. From that documentation:
SO_RCVTIMEO DWORD Sets the timeout, in milliseconds, for blocking receive calls.
(emphasis mine)
It's this limitation in the underlying native API that is the reason for the same limitation in the managed API. Timeout values will not apply to asynchronous I/O on the network objects.
You will need to implement the timeout yourself, by closing the socket if and when the timeout should occur. For example:
async Task<int> ReadAsync(TcpClient client, byte[] buffer, int index, int length, TimeSpan timeout)
{
Task<int> result = client.GetStream().ReadAsync(buffer, index, length);
await Task.WhenAny(result, Task.Delay(timeout));
if (!result.IsCompleted)
{
client.Close();
}
return await result;
}
Other variations on this theme can be found in other related questions:
NetworkStream.ReadAsync with a cancellation token never cancels
Cancel C# 4.5 TcpClient ReadAsync by timeout
Closing the socket is really all that you can do. Even for synchronous operations, if a timeout occurs the socket would no longer be usable. There is no reliable way to interrupt a read operation and expect the socket to remain consistent.
Of course, you do have the option of prompting the user before closing the socket. However, if you were to do that, you would implement the timeout at a higher level in your application architecture, such that the I/O operations themselves have no awareness of timeouts at all.
I'm currently rewriting my TCP server from using StreamSocketListener to TcpListener because I need to be able to use SSL. Since it was some time ago that I wrote the code I'm also trying to make it more cleaner and easier to read and hopefully increase the performance with higher number of clients but I'm currently stuck.
I'm calling a receive method recursively until the client disconnects but I'm starting to wonder if it wouldn't be a better to use a single long running task for it. But I hesitate to use it since it will then create a new long running task for every connected client. That's why I'm turning to the Stack Overflow community for some guidance on how to proceed.
Note: The connection is supposed to be open 24/7 or as much as possible for most of the connected clients.
Any comments are appreciated.
The current code looks something like this:
private async Task ReceiveData(SocketStream socket) {
await Task.Yield();
try {
using (var reader = new DataReader(socket.InputStream)) {
uint received;
do {
received = await reader.LoadAsync(4);
if (received == 0) return;
} while (reader.UnconsumedBufferLength < 4);
if (received == 0) return;
var length = reader.ReadUInt32();
do {
received = await reader.LoadAsync(length);
if (received == 0) return;
} while (reader.UnconsumedBufferLength < length);
if (received == 0) return;
// Publish the data asynchronously using an event aggregator
Console.WriteLine(reader.ReadString(length));
}
ReceiveData(socket);
}
catch (IOException ex) {
// Client probably disconnected. Can check hresult to be sure.
}
catch (Exception ex) {
Console.WriteLine(ex);
}
}
But I'm wondering if I should use something like the following code instead and start it as a long running task:
// Not sure about this part, never used Factory.StartNew before.
Task.Factory.StartNew(async delegate { await ReceiveData(_socket); }, TaskCreationOptions.LongRunning);
private async Task ReceiveData(SocketStream socket) {
try {
using (var reader = new DataReader(socket.InputStream)) {
while (true) {
uint received;
do {
received = await reader.LoadAsync(4);
if (received == 0) break;
} while (reader.UnconsumedBufferLength < 4);
if (received == 0) break;
var length = reader.ReadUInt32();
do {
received = await reader.LoadAsync(length);
if (received == 0) break;
} while (reader.UnconsumedBufferLength < length);
if (received == 0) break;
// Publish the data asynchronously using an event aggregator
Console.WriteLine(reader.ReadString(length));
}
}
// Client disconnected.
}
catch (IOException ex) {
// Client probably disconnected. Can check hresult to be sure.
}
catch (Exception ex) {
Console.WriteLine(ex);
}
}
In the first, over-simplified version of the code that was posted, the "recursive" approach had no exception handling. That in and of itself would be enough to disqualify it. However, in your updated code example it's clear that you are catching exceptions in the async method itself; thus the method is not expected to throw any exceptions, and so failing to await the method call is much less of a concern.
So, what else can we use to compare and contrast the two options?
You wrote:
I'm also trying to make it more cleaner and easier to read
While the first version is not really recursive, in the sense that each call to itself would increase the depth of the stack, it does share some of the readability and maintainability issues with true recursive methods. For experienced programmers, comprehending such a method may not be hard, but it will at the very least slow down the inexperienced, if not make them scratch their heads for awhile.
So there's that. It seems like a significant disadvantage, given the stated goals.
So what about the second option, about which you wrote:
…it will then create a new long running task for every connected client
This is an incorrect understanding of how that would work.
Without delving too deeply into how async methods work, the basic behavior is that an async method will in fact return at each use of await (ignoring for a moment the possibility of operations that complete synchronously…the assumption is that the typical case is asynchronous completions).
This means that the task you initiate with this line of code:
Task.Factory.StartNew(
async delegate { await ReceiveData(_socket); },
TaskCreationOptions.LongRunning);
…lives only long enough to reach the first await in the ReceiveData() method. At that point, the method returns and the task which was started terminates (either allowing the thread to terminate completely, or to be returned to the thread pool, depending on how the task scheduler decided to run the task).
There is no "long running task" for every connected client, at least not in the sense of there being a thread being used up. (In some sense, there is since of course there's a Task object involved. But that's just as true for the "recursive" approach as it is for the looping approach.)
So, that's the technical comparison. Of course, it's up to you to decide what the implications are for your own code. But I'll offer my own opinion anyway…
For me, the second approach is significantly more readable. And it is specifically because of the way async and await were designed and why they were designed. That is, this feature in C# is specifically there to allow asynchronous code to be implemented in a way that reads almost exactly like regular synchronous code. And in fact, this is borne out by the false impression that there is a "long running task" dedicated to each connection.
Prior to the async/await feature, the correct way to write a scalable networking implementation would have been to use one of the APIs from the "Asynchronous Programming Model". In this model, the IOCP thread pool is used to service I/O completions, such that a small number of threads can monitor and respond to a very large number of connections.
The underlying implementation details actually do not change when switching over to the new async/await syntax. The process still uses a small number of IOCP thread pool threads to handle the I/O completions as they occur.
The difference is that the when using async/await, the code looks like the kind of code that one would write if using a single thread for each connection (hence the misunderstanding of how this code actually works). It's just a big loop, with all the necessary handling in one place, and without the need for different code to initiate an I/O operation and to complete one (i.e. the call to Begin...() and later to End...()).
And to me, that is the beauty of async/await, and why the first version of your code is inferior to the second. The first fails to take advantage of what makes async/await actually useful and beneficial to code. The second takes full advantage of that.
Beauty is, of course, in the eye of the beholder. And to at least a limited extent, the same thing can be said of readability and maintainability. But given your stated goal of making the code "cleaner and easier to read", it seems to me that the second version of your code serves that purpose best.
Assuming the code is correct now, it will be easier for you to read (and remember, it's not just you today that needs to read it…you want it readable for the "you" a year from now, after you haven't seen the code for awhile). And if it turns out the code is not correct now, the simpler second version will be easier to read, debug, and fix.
The two versions are in fact almost identical. In that respect, it almost doesn't matter. But less code is always better. The first version has two extra method calls and dangling awaitable operations, while the second replaces those with a simple while loop. I know which one I find more readable. :)
Related questions/useful additional reading:
Long Running Blocking Methods. Difference between Blocking, Sleeping, Begin/End and Async
Is async recursion safe in C# (async ctp/.net 4.5)?
I have a program that begins itself by listening for connections. I wanted to implement a pattern in which the server would accept a connection, pass that individual connection to a user class for processing: future packet reception, and handling of the data.
I ran into trouble with the synchronous pattern before I found out that asynchronous use of the Socket class isn't scary. But then I ran into more trouble. It seemed that, in a while (true) loop, since BeginAccept() is asynchronous, the program would constantly move through this loop and eventually run into an OutOfMemoryException. I needed something to listen for a connection, and immediately hand off responsibility of that connection to some other class.
So I read Microsoft's example and found out about ManualResetEvent. I could actually specify when I was ready for the loop to begin listening again! But after reading some questions here on Stack Overflow, I have become confused.
My worry is that even though I have asynchronously accepted a connection, the entire program will block while it's trying to listen for a new connection upon re-entering the loop. This isn't ideal if I'm handling multiple users.
I'm very new to the world of asynchronous I/O, so I would appreciate even the angriest of comments about my vocabulary or a misuse of a phrase.
Code:
static void Main(string[] args)
{
MainSocket = new Socket(SocketType.Stream, ProtocolType.Tcp);
MainSocket.Bind(new IPEndPoint(IPAddress.Parse("192.168.1.74"), 1626));
MainSocket.Listen(10);
while (true)
{
Ready.Reset();
AcceptCallback = new AsyncCallback(ConnectionAccepted);
MainSocket.BeginAccept(AcceptCallback, MainSocket);
Ready.WaitOne();
}
}
static void ConnectionAccepted(IAsyncResult IAr)
{
Ready.Set();
Connection UserConnection = new Connection(MainSocket.EndAccept(IAr));
}
The Microsoft example, in which they use the old-style WaitHandle based events, will work but frankly it is a very odd and awkward way to implement asynchronous code. I get the feeling that the events are there in the example mainly as a way of artificially synchronizing the main thread so it has something to do. But it's not really the right approach.
One option is to just not even accept sockets asynchronously. Instead, use the asynchronous I/O for when the socket is connected and use a synchronous loop in the main thread to accept sockets. This winds up being pretty much exactly what the Microsoft sample does anyway, but keeps all of the accept logic in the main thread instead of switching back and forth between the main thread (which starts the accept operation) and some IOCP thread that handles the completion.
Another option is to just give the main thread something else to do. For a simple example, this could be simply waiting for some user input to signal that the program should shut down. Of course, in a real program the main thread could be something useful (e.g. handling the message loop in a GUI program).
If the main thread is given something else to do, then you can use the asynchronous BeginAccept() in the way it was intended: you call the method to start the accept operation, and then don't call it again until that operation completes. The initial call happens when you initialize your server, but all subsequent calls happen in the completion callback.
In that case, your completion callback method looks more like this:
static void ConnectionAccepted(IAsyncResult IAr)
{
Connection UserConnection = new Connection(MainSocket.EndAccept(IAr));
MainSocket.BeginAccept(ConnectionAccepted, MainSocket);
}
That is, you simply call the BeginAccept() method in the completion callback itself. (Note that there's no need to create the AsyncCallback object explicitly; the compiler will implicitly convert the method name to the correct delegate type instance on your behalf).
I'm trying to use HttpResponse BeginFlush and EndFlush methods in order to make the flush async, which means my worker thread won't being used while flushing to the stream.
However it seems that the BeginFlush methods run in synchronous way always.
I dig in Microsoft reference code and didn't find the reason for this behavior.
This is Microsoft implementation: http://referencesource.microsoft.com/#System.Web/HttpResponse.cs,f121c649c992c407
I checked the SupportsAsyncFlush flag and I'm getting true , so my environment actually supports the AsyncFlush.
Any idea?
This is a code snippet for trying to do the async flush, but I'm not getting to the "Different Threads" line - it is always the same thread that runs this code.
Context.Response.Write("Some message");
Context.Response.BeginFlush(
res =>
{
try
{
var previousThreadId = (int)res.AsyncState;
var thread2Id = Thread.CurrentThread.ManagedThreadId;
if (previousThreadId != thread2Id)
{
Console.WriteLine("Different Threads");
}
Context.Response.EndFlush(res);
}
catch (Exception e)
{
}
},
Thread.CurrentThread.ManagedThreadId);
The code is asynchronous, but it's not multithreaded. You're defining a callback; a method that will be run at some indeterminate point in the future when the flush finishes. That doesn't necessarily mean that it'll run on another thread.
There are also many implementations of abstract functionality in .NET where the behavior is defined as asynchronous, but the implementation is synchronous because that particular implementation expects to run so quickly as to not warrant asynchrony. This is true for a fair bit of .NET's file IO. If the writer you're using expects to be able to flush the buffer very quickly, it may not bother doing it asynchronously.
The effect you are seeing may be related to SycnhronizationContext used by ASP.NET. Depending on .NET version and whether your code executes under ASP.NET page or something else, the behavior may change. Generally, it is normal for the SynchronizationContext to execute the callback on the same thread which started the async operation. You can find more info here: https://msdn.microsoft.com/en-us/magazine/gg598924.aspx
In any case, you can check whether the callback is synchronous or not by checking weather the next line of your code (after BeginFlush) executes before the callback. That will indicate that the callback is indeed asynchronous.
I currently have a background thread. In this thread is a infinite loop.
This loop once in a while updates some values in a database, and then listens 1 second on the MessageQueue (with queue.Receive(TimeSpan.FromSeconds(1)) ).
As long as no message comes in, this call then internally throws a MessageQueueException (Timeout) which is caught and then the loop continues. If there is a message the call normally returns and the message is processed, after which the loop continues.
This leads to a lot of First chance exceptions (every second, except there is a message to process) and this spams the debug output and also breaks in the debugger when I forgot to exclude MessageQueueExceptions.
So how is the async handling of the MessageQueue meant to be done correctly, while still ensuring that, as long as my application runs, the queue is monitored and the database is updated too once in a while. Of course the thread here should not use up 100% CPU.
I just need the big picture or a hint to some correctly done async processing.
Rather than looping in a thread, I would recommend registering a delegate for the ReceiveCompleted event of your MessageQueue, as described here:
using System;
using System.Messaging;
namespace MyProject
{
///
/// Provides a container class for the example.
///
public class MyNewQueue
{
//**************************************************
// Provides an entry point into the application.
//
// This example performs asynchronous receive operation
// processing.
//**************************************************
public static void Main()
{
// Create an instance of MessageQueue. Set its formatter.
MessageQueue myQueue = new MessageQueue(".\\myQueue");
myQueue.Formatter = new XmlMessageFormatter(new Type[]
{typeof(String)});
// Add an event handler for the ReceiveCompleted event.
myQueue.ReceiveCompleted += new
ReceiveCompletedEventHandler(MyReceiveCompleted);
// Begin the asynchronous receive operation.
myQueue.BeginReceive();
// Do other work on the current thread.
return;
}
//**************************************************
// Provides an event handler for the ReceiveCompleted
// event.
//**************************************************
private static void MyReceiveCompleted(Object source,
ReceiveCompletedEventArgs asyncResult)
{
// Connect to the queue.
MessageQueue mq = (MessageQueue)source;
// End the asynchronous Receive operation.
Message m = mq.EndReceive(asyncResult.AsyncResult);
// Display message information on the screen.
Console.WriteLine("Message: " + (string)m.Body);
// Restart the asynchronous Receive operation.
mq.BeginReceive();
return;
}
}
}
Source: https://learn.microsoft.com/en-us/dotnet/api/system.messaging.messagequeue.receivecompleted?view=netframework-4.7.2
Have you considered a MessageEnumerator which is returned from the MessageQueue.GetMessageEnumerator2 ?
You get a dynamic content of the queue to examine and remove messages from a queue during the iteration.
If there are no messages then MoveNext() will return false and you don't need to catch first-chance exceptions
If there are new messages after you started iteration then they will be iterated over (if they are put after a cursor).
If there are new messages before a cursor then you can just reset an iterator or continue (if you don't need messages with lower priority at the moment).
Contrary to the comment by Jamie Dixon, the scenario IS exceptional. Note the naming of the method and its parameters: BeginReceive(TimeSpan timeout)
Had the method been named BeginTryReceive, it would've been perfectly normal if no message was received. Naming it BeginReceive (or Receive, for the sync version) implies that a message is expected to enter the queue. That the TimeSpan parameter is named timeout is also significant, because a timeout IS exceptional. A timeout means that a response was expected, but none was given, and the caller chooses to stop waiting and assumes that an error has occured. When you call BeginReceive/Receive with a 1 second timeout, you are stating that if no message has entered the queue by that time, something must have gone wrong and we need to handle it.
The way I would implement this, if I understand what you want to do correctly, is this:
Call BeginReceive either with a very large timeout, or even without a timeout if I don't see an empty queue as an error.
Attach an event handler to the ReceiveCompleted event, which 1) processes the message, and 2) calls BeginReceive again.
I would NOT use an infinite loop. This is both bad practice and completely redundant when using asynchronous methods like BeginReceive.
edit: To abandon a queue which isn't being read by any client, have the queue writers peek into the queue to determine if it is 'dead'.
edit: I have another suggestion. Since I don't know the details of your application I have no idea if it is either feasible or appropriate. It seems to me that you're basically establishing a connection between client and server, with the message queue as the communication channel. Why is this a 'connection'? Because the queue won't be written to if no one is listening. That's pretty much what a connection is, I think. Wouldn't it be more appropriate to use sockets or named pipes to transfer the messages? That way, the clients simply close the Stream objects when they are done reading, and the servers are immediately notified. As I said, I don't know if it can work for what you're doing, but it feels like a more appropriate communication channel.