TCPlistener.BeginAcceptSocket - async question - c#

Some time ago I have payed to a programmer for doing multithread server. In the meantime I have learned C# a bit and now I think I can see the slowndown problem - I was told by that guy that nothing is processed on the main thread (Form) so it cannot be frozen..but it is.
But I think that altough BeginAcceptSocket is async operation, but its callback runs on the main thread and if there is locking, thats the reason why the app freezes. Am I right?
Thanks
this.mTcpListener.BeginAcceptSocket(this.AcceptClient, null);
protected void AcceptClient(IAsyncResult ar)
{
//some locking stuff
}

No, AcceptClient() will not run on the main thread.
Better show some of the 'locking stuff'.

The Begin/End asynchronous IO methods use ThreadPool threads to execute the callback delegate, unless the operation can be completed instantly; in which case it executes synchronously on the calling thread.
From Calling Synchronous Methods Asynchronously:
Pass a delegate for a callback method to BeginInvoke. The method is executed on a ThreadPool thread when the asynchronous call completes. The callback method calls EndInvoke.
The callback should not often be occurring on the GUI thread.
If the application window becomes unresponsive, it may be as a result of excessive invoking of methods on the GUI thread - usually to update controls.

I made small winapp test and the result is that even if 'AcceptClient' method is declared in the same class than this delegate is invoked from other thread than main winform app thread, and thus NO blocking is there.

Anytime that your code gets a lock and then does something you have a candidate for a bottleneck, however, the thread that calls BeginAcceptSocket won't be blocked and can continue to do work until the callback event happens. It won't execute the callback handler until then so, in your example, none of the locking will occur until it has been contacted by a client. It still may be hanging up in the accept code if whatever it does at that point takes time or gets delayed due to communication issues, but it's hard to tell from your code sample if that's the case.

AcceptClient(IAsyncResult ar) callback may be completed synchronously.
I guess if BeginAccept encounters that there is a new client it can execute callback method synchronously.
To be sure you have to stop your application under debugger when it froze and see what Main (event) thread is doing.
Generally it is better to have separate thread for doing any I/O.

Related

Difference between when the callback runs in JavaScript vs C#

JavaScript callback runs only when the call stack is empty. That happens either when the program execution finishes or when the main program calls await.
The callback in case of Task library in C#:
Assuming single thread program, behaves the same as JS (assuming await is used and not .Wait which would cause deadlock).
However in case of using Task.Run, or configure await false, the callback will run immediately when the response is ready. I am assuming each thread has its own call stack.
Is this correct distinction between when the callback runs in case of JS and C#?
Is this correct distinction between when the callback runs in case of JS and C#?
Not really.
In JavaScript, the continuation always runs on the main thread when it is not doing anything else. Even if you await a Promise that's already complete, it's as though you called setTimeout without a delay. The code always yields whenever there's an await. IMO, the JavaScript approach is cleaner and easier to understand than C#. However, the .NET team adopted a different approach for C#, I assume for performance reasons.
In C#, the first thing to note is that await may continue executing synchronously. If the awaitable is already complete, then there's no yielding that takes place and no continuation exists at all - the code just continues executing in the same method. If the awaitable is not already complete, then a continuation is attached to the awaitable along with the current context (SynchronizationContext.Current or TaskScheduler.Current).
When the awaitable completes, then it executes all its continuations. If it's possible, then the continuation is executed on the current thread (the one that completed the awaitable). If this kind of "inline continuation" isn't possible, then the continuation is queued to the context (SynchronizationContext / TaskScheduler). What happens then is entirely dependent on the context. E.g., UI contexts will queue continuations to the UI message processing loop, which is pretty much the same as setTimeout in JavaScript. As another example, the thread pool context will queue continuations to the thread pool.
Main difference is: single-thread vs multi-thread
I think, in your case, callback is called from different thread.
Learn more about TaskScheduler and SynchronizationContext to achieve your endeavour.

Why does Control.Invoke() calls PostMessage() instead of SendMessage()?

Control.Invoke() calls PostMessage() and then waits until the UI thread finishes processing the message. So why it does not calls SendMessage() instead (which by default waits until the UI thread finishes processing the message).
Control.Invoke() is a dangerous method, many .NET programmers have deadlocked their program with it. It should be very strongly avoided because of this. Simple everyday operations like closing a window become perilous. You'll want to wait until a worker thread cannot invoke anymore since nothing good happens when the thread keeps running but the UI is gone. So you signal the thread with, say, AutoResetEvent and wait for it to complete.
Such a wait is very likely to deadlock your program when the thread is calling Invoke() at just the wrong time. The thread cannot complete because it is stuck in the Invoke() call, the UI thread cannot service it since it is stuck in the wait. A "deadly embrace", neither thread can make progress and your program will hang. Quite hard to debug since it is not predictable and doesn't happen often enough, only goes wrong when the thread calls Invoke at exactly the same time.
Breaking that deadlock requires knowing that an Invoke() call is in progress so it can be cancelled. It is not knowable when you use SendMessage(). The lock on which it blocks is hidden in the OS. I've recently posted an answer about the problems with SendMessage, everything you read there applies here as well.
So Microsoft did not implement it that way and they use PostMessage. They add an entry to the invoke queue, call PostMessage to wake up the UI thread so it goes looking through that queue. And specific to Invoke over BeginInvoke, they block on a ManualResetEvent in the queue entry, signaled when the UI thread completed the call to the delegate target.
Now they can do something to avoid the deadlock, when a window closes it looks through the invoke queue and cancels any that had that window as the invoke target. Or in other words, the lock that's invisible when you use SendMessage and causes deadlock now becomes visible and can be released to break the deadlock.

Is rampant use of Control.Invoke and Control.InvokeRequired healthy?

I am writing a client server application that works like this:
Form1 loads and creates ServerHost. ServerHost is started to listen for TcpClient connections, on connected and accepted, ServerHost spawns a thread by way of ThreadPool.QueueUserWorkItem(DoWork, client);
Within the DoWork() thread, I want to update Winform Controls on Form1.
This is achieved by having events in ServerHost such as ServerHost.SomethingHappened. When something happened in DoWork(), it raises the event and the Form1.Handler is called to update the winforms control.
This set up gives me cross-thread operation error.
Is use of Control.Invoke and Control.InvokeRequired healthy? I am not good at threads, and MSDN is saying to use BackgroundWorker, but I can't see how to do it here. Any advice to change the structure to avoid using Invoke in this set up?
Control.Invoke is highly questionable, and Control.InvokeRequired is downright toxic.
If at all possible, use the new async/await support, and you won't need to explicitly marshal back to the UI thread. Also, use Task.Run instead of ThreadPool.QueueUserWorkItem for background work.
The problem with Control.Invoke is that it ties your library to a specific UI (WinForms). Capturing a SynchronizationContext is a step above that, and implicitly capturing the SynchronizationContext by using await is even better.
You have to invoke the code that updates the user interface on the UI thread.
In general there are several options to do that:
calling Invoke on a Control
using a BackgroundWorker that has been started on the UI thread
calling Post on the SynchronizationContext of the UI thread
using Task.ContinueWith with the TaskScheduler of the UI thread
using asynchronous calls with async/await
In my opinion last method is by far the easiest for the developer, but it is only available with C# 5 and .NET 4.5 or .NET 4.0 with the Microsoft.Bcl.Async package. Tasks are nearly as easy to use but both of these methods would require you to change your code. They won't work to simply invoke a method on the UI thread from a thread pool thread.
The BackgroundWorker is usually used to schedule an action that takes quite some time. Its ReportProgress method raises the ProgressChanged event on the thread that called the RunWorkerAsync method. As such it is also not a good solution to your problem.
SynchronizationContext.Post and Control.Invoke work similarly, but Control.Invoke doesn't require you to capture the UI context, so it's easier to use.
To summarize it you should use Control.Invoke unless you want to change your code to make use of async/await.
It's fine as long as the UI thread isn't overburdened by those invokes. It does introduce some latency to the communication, which usually isn't an issue, however, it can become more of a problem if you're doing a lot of Invokes, or if the UI thread is doing a lot of work (eg. rendering complex graphs or something like that). Invoke is a synchronous method - it will not return until the invoked command is actually processed, and returns its return value.
As long as you're not tied up by these issues, all is well. Profiling and performance testing is critical to allocate your resources correctly, guessing is usually a huge waste of time and resources.
If you don't need the resulting value (or at least not synchronously) and you're starting to get into performance trouble, have a look at BeginInvoke, which handles the invoking asynchronously. This means your networking thread doesn't have to wait for the UI thread to work. This is quite critical in high performance servers with thousands of connections. They simply can't afford to wait while the UI does its thing.
However, do note, that having a server socket running on a different thread is not a good solution for larger servers, and in fact, it's no longer the easiest solution either. .NET now has great support for asynchronous calls and callbacks, making implementations of asynchronous processing a breeze. In your typical Winforms application, it means that I/O blocking applications can work without having constantly running and polling threads. For example, waiting for a new connection can be as simple as:
var connection = await listener.AcceptTcpClientAsync();
That's it. Automagically, all the callbacks will be processed at the right time, without blocking the processing, all of your own code always running on the main UI thread. In other words, you can easily do this:
while (!aborted)
{
var connection = await listener.AcceptTcpClientAsync();
tbxLog.Text += "New connection!\r\n";
}
While this seems like an infinite loop blocking the UI thread indefinitely, the reality is that when the application gets to the await keyword, it will register an asynchronous callback and returns. Only when the asynchronous callback is actually invoked (by IOCP in this case) is the code resumed (on the UI thread), and tbxLog has the text appended, followed by waiting for another connection.
I've never had problems doing it this way. No matter how you set it up, updating your controls has to be done on the thread they were created on. If you use a BackgroundWorker or some other async construct, somewhere an invoke is going to be called. I typically create a method on the form like:
delegate void TextSetter(string text);
internal void SetText(string text)
{
//call on main thread if necessary
if (InvokeRequired)
{
this.Invoke((TextSetter)SetText, text);
return;
}
//set the text on your label or whatever
this.StatusLabel.Text = text;
}
I've used that method in a number of applications and it's never been a problem, even updating many times per second.
As far as I'm aware, the only way to get around calling an invoke is to have your main thread constantly poll for updates, which is generally accepted as a really bad way to do things.
A really obvious simplification is to abstract away the InvokeRequired/Invoke into an extension method for a Control.
public static class FormExt {
public static void Execute(this Control c, Action a) {
if (c.InvokeRequired) {
c.Invoke(a);
} else {
a();
}
}
}
Now you just wrap up normal form updates into a lambda and execute them.
form1.Execute(() => form1.Text = "Hello world");

On which thread do Async Callbacks run?

I'm making several HttpWebRequest.BeginGetResponse calls, and in the callback method of the BeginGetResponse, I'm invoking an EventHandler. In the EventHandler, there is logic to test if the download was successful. If not, it tries to redownload the Html. I'm noticing lots of threads being generated especially when there are errors. So, on which thread do the Async Callbacks run?
Is there anyway I can invoke the EventHandler on the original thread? If that is not posible, can I invoke it on the UI thread?
Thanks!
Callbacks are made on a threadpool thread. There is no mechanism in .NET to make code run on a specific thread. That is very hard to come by, you can't just interrupt a thread while it is busy and make it run some code. That causes horrible re-entrancy problems that a lock cannot solve.
A thread must be in an idle state, not actively mutating the state of the program. There's one kind of thread that behaves that way, the UI thread in a Winforms or WPF app. That's also the thread that has to deal with objects that are fundamentally thread-unsafe, anything related to the UI. This is not a coincidence.
Both class libraries make it possible to marshal a call from a worker thread to the UI thread, specifically to help getting the UI updated in a thread-safe way. In Winforms you use Control.Begin/Invoke(), in WPF you use Dispatcher.Begin/Invoke(). BackgroundWorker is a handy class to get this done without explicitly managing the marshaling. But isn't suitable for I/O completion callbacks.
What do you mean by "on the original thread"? Which original thread? You can marshal to the UI thread using Control.BeginInvoke or Dispatcher.BeginInvoke. You can't marshal to an arbitrary thread - it has to have something like a message pump waiting for work.
As for which thread HttpWebRequest async callbacks are executed on - I would expect either a general thread pool worker thread, or possibly an IO completion port thread.
Using the Begin/End Async pattern, be aware that it's possible for many kinds of tasks to complete on the thread they were called from. When you call BeginXXX, it returns a boolean that signifies if the task was completed on the calling thread or not.
The basic answer is, it could be any thread.
If you are using WPF you can use the Dispatcher to invoke your logic on the UI thread.
Otherwise, (if not in WPF) you could use a SyncrhronizationContext to accomplish the same thing.

Use of IAsyncResult.AsyncWaitHandle

In the asynchronous programming model, there looks to be 4 ways (As stated in Calling Synchronous Methods Asynchronously) for making asynchronous method calls.
Calling the EndInvoke() method makes the calling thread wait for the method completion and returns the result.
Going through the IAsyncResult.AsyncWaitHandle.WaitOne() also seem to do the same. AsyncWaitHandle gets a signal of completion (In other word the main thread waits for the Asynchronous method's completion). Then we can execute EndInvoke() to get the result.
What is the difference between calling the EndInvoke() directly and calling it after WaitOne()/WaitAll()?
In the polling technique we provide time for other threads to utilize the system resources by calling Thread.Sleep().
Does AsyncWaitHandle.WaitOne() or EndInvoke() make the main thread go on sleep while waiting?
Q1. There is no difference in the way your code runs or your application, but there might be some runtime differences (again not sure, but a guess based my understanding of Async delegates).
IAsyncResult.AsyncWaitHandle is provided mainly as a synchronization mechanism while using WaitAll() or WaitAny() if you dont have this synchronization need you shouldn't read AsyncWaitHandle property. Reason : AsyncWaitHandle doesnt have to be implemented (created) by the delegate while running asynchronously, until it is read by the external code. I'm not sure of the way CLR handles the Async delegates and whether it creates a WaitHandler or not, but ideally if it can handle running your async delegates without creating another WaitHandle it will not, but your call to WaitOne() would create this handle and you have extra responsibility of disposing(close) it for efficient resource release. Therefore recommendation would be when there is no sycnchronization requirement which can be supported with WaitAll() or WaitAny() dont read this property.
Q2. This Question answers the difference between Sleep and Wait.
Simple things first. For your second question, yes, WaitOne and EndInvoke does indeed make the current thread sleep while waiting.
For your first questions, I can immediately identify 2 differences.
Using WaitOne requires the wait handle to be released, while using EndInvoke directly doesn't require any cleanup.
In return, using WaitOne allows for something to be done before EndInvoke, but after the task has been completed.
As for what that "something" might be, I don't really know. I suspect allocating resources to receive the output might be something that would need to be done before EndInvoke. If you really have no reason to do something at that moment, try not to bother yourself with WaitOne.
You can pass a timeout to WaitOne, so you could, for instance want to perform some other activities on a regular basis whilst waiting for the operation to complete:
do {
//Something else
) while (!waitHandle.WaitOne(100))
Would do something every ~100 milliseconds (+ whatever the something else time is), until the operation completed.

Categories