HttpWebRequest.BeginGetResponse callback on the same thread - c#

Is it possible that a call to a Begin... method (that takes a callback and an object and returns an IAsyncResult), specifically HttpWebRequest.BeginGetResponse, will call the callback on the same thread, thus if not handled correctly will cause a hang in case the callback releases a wait-handle?
If so, what is the best way to handle that case? Should I use the return value to make sure the request was already handled and release the wait-handle (or not wait on it in the first place)? Will the callback be called in such case?
I know it happens for sure with HttpWebRequest.BeginGetRequestStream (I learned it the hard way). But is it possible it'll happen with HttpWebRequest.BeginGetResponse also?
What I'm facing are rare hangs of the test suite and I narrowed it down to the communication library, where (unless I missed something) all relevant communication are being done asynchronously with HttpWebRequest.BeginGetResponse and AutoResetEvent for wait handles.

Related

Do you have to await async methods?

Lets say you have a service API call. The callee is somewhat performance critical, so in order not to hold up the API call any longer than necessary, there's an SaveAsync() method that is used. I can't await it, however, because that would hold up the API call just as long (or perhaps even longer) than the non-async version.
The reason I'm asking is this: If you don't await the call, is there a chance the Task object returned gets garbage collected? And if so, would that interrupt the running task?
The reason I'm asking is this: If you don't await the call, is there a chance the Task object returned gets garbage collected?
Generally, no, that shouldn't happen. The underlying TaskScheduler which queues the task, usually keeps a reference to it for the desired life-time until it completes. You can see that in the documentation of TaskScheduler.QueueTask:
A typical implementation would store the task in an internal data structure, which would be serviced by threads that would execute those tasks at some time in the future.
Your real problem is going to be with the ASP.NET SynchronizationContext, which keeps track of any on-going asynchronous operation at runtime. If your controller action finishes prior to the async operation, you're going to get an exception.
If you want to have "fire and forget" operations in ASP.NET, you should make sure to register them with the ASP.NET runtime, either via HostingEnvironment.QueueBackgroundWorkItem or BackgroundTaskManager
No, it won't interrupt the running task, but you won't observe the exceptions from the task either, which is not exactly good. You can (at least partially) avoid that by wrapping all running code in a try ... catch and log the exception.
Also, if you're inside asp.net, then your whole application could be stopped or recycled, and in this case your task will be interrupted. This is harder to avoid - you can register for AppPool shutdown notification, or use something like Hangfire.

Task equivalent that can be killed at once

I want to run a long running opeartion in the background.
The requirements are:
The operation should run async to the calling thread.
The calling thread can wait on the operation to complete and obtain its result
Upon timeout, the operation should be aborted at once.
I would have used task, but there is no mechanism that I know of to kill the task dead cold.
Cancel token is not suitable for me, I would only kill a task if it gets stuck for unknown reason - (a bug) , this is a fail-safe mechanism.
Needles to say if the task is stuck, there is no use in requesting cancel.
Same goes for BackgroundWorker.
Is there anything more elagent than using a shared object between the calling thread and a background thread?
There is nothing more elegant than using a shared object, since using a shared object is the elegant way of doing this :)
You cant provide a generic way of killing a task safely: Since the killer thread does not have any clue of what the killee is doing when trying to kill it, this would potentially leave your object model in a "corrupted" state.
Thread.Abort() has been created to do that the cleanest way possible: By throwing an exception (which allows "finally" statements to dispose used resources, or running transactions disposal on killed thread). But this method can make the code throw an exception in unexpected location. It is highly not recommended.
nb: Thread.Abort() does not work in any case (example: wont work if your thread is running native code via a P/Invoke for instance)
Thus, the elegant solution is to write clean code, which can decide when it wants to be killed (via a cancellation token).
nb2: The ultimate "Thread.Abort()" which will work in any case, and which which will keep things isolated: Create a new AppDomain, run your killable code in this AppDomain (via remoting), and call AppDomain.Unload() when you want to stop everything.
This is a quite extreme solution, though.
The only way to kill a thread 'dead cold' that I know of is Thread.Abort, however, you will see a lot of answers to this related question, Killing a Thread C#, indicating that it is generally bad practice to use it, except in rare occasions.
Another option is to avoid trying to kill the task dead cold and implement better error handling in your task such that it gracefully handles exceptions and situations where it 'gets stuck'.

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.

Is the callBack method called before the assignment or after here?

I have the code below which is basically calling a Domain Service in a SilverLight Application.
LoadOperation<tCity> loadOperation = _dataContext.Load(query,callBack, true);
Can you tell me which operation is done first?
Is the callBack method called before loadOperation variable is assigned or after it is assigned?
Thanks
Assuming it's meant to be an asynchronous operation, it could happen either way, in theory. The asynchronous operation should occur in another thread, and if that finishes before Load returns, the callback could be called before the assignment completes.
In practice, I'd expect the async call to take much longer than whatever housekeeping Load does at the end of the method - but I also wouldn't put that assumption into the code. Unless there's explicit synchronization to ensure that the assignment occurs before the callback, I don't think it's a good idea to rely on it.
Even if at the moment the assignment always happens first, consider:
What happens if there's no network connection at the moment? The async call could fail very quickly.
What happens if some caching is added client-side? The call could succeed very quickly.
I don't know what kind of testing you're able to do against the RIA services, but sometimes you may want to be able to mock asynchronous calls by making them execute the callback on the same thread - which means the callback could happen in tests before the assignment. You could avoid this by forcing a genuinely asynchronous mock call, but handling threading in tests can get hairy; sometimes it's easiest just to make everything synchronous.
EDIT: I've been thinking about this more, and trying to work out the reasons behind my gut feeling that you shouldn't make this assumption, even though it's almost always going to be fine in reality.
Relying on the order of operations is against the spirit of asynchronicity.
You should (IMO) be setting something off, and be ready for it to come back at any time. That's how you should be thinking about it. Once you start down the slippery slope of "I'm sure I'll be able to just do a little bit of work before the response is returned" you end up in a world of uncertainty.
First, I would say write your callback without any assumptions. But aside from that I don't see how the callback could possibly occur before the assignment. The load operation would have to return immediately after the thread is spun.
There are 3 possible answers to this very specific RIA Services question:
It returns the assignment before the callback.
It may be possible for the callback to occur before the assignment.
You do not care.
Case 1:
Based on a .Net Reflector investigation of the actual load method in question, it appears impossible for it to call the callback before the return occurs. (If anyone wants to argue that they are welcome to explain the intricacies of spinning up background threads).
Case 2:
Proof that "the sky is falling" is possible would have to be shown in the reflected code. (If anyone wants to support this they are also welcome to explain the intricacies of spinning up background threads).
Case 3:
In reality, the return value of a RIA Services load method is normally used to assign a lazy loading data source. It is not used by the callback. The callback is passed its own context, of the loaded data, as a parameter.
StackOverflow is all about practical code answers, so the only practical answer is option 3:
You do not care (as you do/should not use the assignment value from the callback).

Letting the client pull data

I'm writing a server in C# which creates a (long, possibly even infinite) IEnumerable<Result> in response to a client request, and then streams those results back to the client.
Can I set it up so that, if the client is reading slowly (or possibly not at all for a couple of seconds at a time), the server won't need a thread stalled waiting for buffer space to clear up so that it can pull the next couple of Results, serialize them, and stuff them onto the network?
Is this how NetworkStream.BeginWrite works? The documentation is unclear (to me) about when the callback method will be called. Does it happen basically immediately, just on another thread which then blocks on EndWrite waiting for the actual writing to happen? Does it happen when some sort of lower-level buffer in the sockets API underflows? Does it happen when the data has been actually written to the network? Does it happen when it has been acknowledged?
I'm confused, so there's a possibility that this whole question is off-base. If so, could you turn me around and point me in the right direction to solve what I'd expect is a fairly common problem?
I'll answer the third part of your question in a bit more detail.
The MSDN documentation states that:
When your application calls BeginWrite, the system uses a separate thread to execute the specified callback method, and blocks on EndWrite until the NetworkStream sends the number of bytes requested or throws an exception.
As far as my understanding goes, whether or not the callback method is called immediately after calling BeginSend depends upon the underlying implementation and platform. For example, if IO completion ports are available on Windows, it won't be. A thread from the thread pool will block before calling it.
In fact, the NetworkStream's BeginWrite method simply calls the underlying socket's BeginSend method on my .Net implementation. Mine uses the underlying WSASend Winsock function with completion ports, where available. This makes it far more efficient than simply creating your own thread for each send/write operation, even if you were to use a thread pool.
The Socket.BeginSend method then calls the OverlappedAsyncResult.CheckAsyncCallOverlappedResult method if the result of WSASend was IOPending, which in turn calls the native RegisterWaitForSingleObject Win32 function. This will cause one of the threads in the thread pool to block until the WSASend method signals that it has completed, after which the callback method is called.
The Socket.EndSend method, called by NetworkStream.EndSend, will wait for the send operation to complete. The reason it has to do this is because if IO completion ports are not available then the callback method will be called straight away.
I must stress again that these details are specific to my implementation of .Net and my platform, but that should hopefully give you some insight.
First, the only way your main thread can keep executing while other work is being done is through the use of another thread. A thread can't do two things at once.
However, I think what you're trying to avoid is mess with the Thread object and yes that is possible through the use of BeginWrite. As per your questions
The documentation is unclear (to me)
about when the callback method will be
called.
The call is made after the network driver reads the data into it's buffers.
Does it happen basically immediately,
just on another thread which then
blocks on EndWrite waiting for the
actual writing to happen?
Nope, just until it's in the buffers handled by the network driver.
Does it happen when some sort of
lower-level buffer in the sockets API
underflows?
If by underflow your mean it has room for it then yes.
Does it happen when the data has been
actually written to the network?
No.
Does it happen when it has been
acknowledged?
No.
EDIT
Personally I would try using a Thread. There's a lot of stuff that BeginWrite is doing behind the scenes that you should probably recognize... plus I'm weird and I like controlling my threads.

Categories