What does CloudQueue.EndAddMessage(IAsyncResult) actually do? - c#

Let's say I call
AsyncCallback callback = new AsyncCallback(QueueMessageAdded);
queue.BeginAddMessage(new CloudQueueMessage(message), callback, null);
where QueueMessageAdded is
private static void QueueMessageAdded(IAsyncResult result)
{
queue.EndAddMessage(result);
}
What does EndAddMessage do?
Including waiting for all callbacks to have been called, it is as slow as calling the synchronous version like this:
Parallel.ForEach(messages, message => queue.AddMessage(message));

First approach makes the request asynchronously and therefore your thread does not have to block while waiting for a response. Second approach, on the other hand, will use N threads, each of which will block until a response is received to its respective request.
Please refer to Asynchronous Programming Model (APM) for more information. All End* methods complete the asynchronous operation, meaning it will block until the operation finishes, return the operation's result if any, and do clean-up.

The first approach allow you to use concurrent requests! A single thread, can, with the first approach send hundreds of concurrent messages, even though the latency of a single POST request to get its reply is high. If you look at production code targeting ASB you can see some patterns in how APM/Async is used.

Related

Why not use a sync method instead of await Async task?

Async method:
public void Main(){
await Asynctask1;
DoSomething();
}
public async Task AsyncTask1(){
//Async logic here
}
Sync method:
public void Main(){
SyncMethod1();
DoSomething();
}
I think I'm missing something here. Assuming that SyncMethod1() and Asynctask1() both do the same thing, aren't these 2 constructs in the end the same result, namely that DoSomething() doesn't start until the method before finishes?
namely that DoSomething() doesn't start until the method before finishes?
There's a difference between asynchrony and sequential. When you always await your asynchronous methods immediately, you end up with asynchronous sequential code, which at first glance does appear to behave similarly to synchronous sequential code. (On a side note, this similarity is the entire point of the async/await keywords). However, there's one important difference.
Let's say the operation is some I/O thing, like getting an HTTP resource. SyncMethod1 will do the HTTP get synchronously; that is, it sends out the HTTP request and then blocks the thread until it gets the HTTP response. AsyncTask1 will do the HTTP get asynchronously; that is, it sends out the HTTP request and then returns an incomplete Task. Later, when the HTTP request comes in, the AsyncTask1 method will resume and complete the returned Task, and the code after the await is run (i.e., DoSomething).
The asynchronous way is more complicated but has one key advantage: it does not block a thread. So, UI threads are freed to enable a responsive UI and ASP.NET threads are freed to handle other requests.
I have an async intro on my blog that may help as you learn.
In the case you have outlined there is no practical difference as you immeadiately wait for the asynchronous method to complete before moving on to the next.
However, if you restructured your code something like this you might realize the power of asynchronous programming:
public async void Main() {
Task performTask = AsyncTask1();
//This method can continue without having to wait for AsyncTask1 to complete
DoSomething();
//Here we await the AsyncTask1 because perhaps other code further
//down is depending on it
await performTask;
}

Can I ignore WCF asynchronous EndXXX call?

I have 2 services servicing WCF calls. From a client I send the same asynchronous WCF BeginXXX call to both services and then start waiting for replies with a WaitHandle.WaitAny(waitHandles) where waitHandles is an array of WaitHandles from the IAsyncResults returned by the 2 BeginXXX calls.
I want to use only the reply from the service that answers faster, i.e. when WaitHandle.WaitAny returns with an index I only call EndXXX with the corresponding IAsyncResult to get the faster result. I don't ever call the other EndXXX.
My reason for doing this is that sometimes a service uses several seconds in garbage collection and is not able to answer fast. According to my experiences the 2 services do garbage collections usually in different times so one of them is almost always capable of returning a fast answer. My client application is very time critical, I need an answer within a few milliseconds.
My questions are:
Can I safely ignore calling EndXXX method for the other service that was slower in answering? I am not interested in the slower result but want to use the faster result ASAP. According to my experiments nothing bad seems to happen even if I don't call the EndXXX method for the corresponding slower BeginXXX async result.
Would somebody mind explaining to me what exactly happens when I don't make an EndXXX call for a corresponding BeginXXX? Under debugger in Visual Studio I seem to able to see that another answer is processed in the .NET framework via an I/O completion port and this processing does not originate from my client calling EndXXX. And I don't seem to have any memory leaks because of not making the EndXXX call. I presume all objects involved are garbage collected.
Does it make any difference whether the server side method XXX implementation is a single synchronous XXX or an explicit asynchronous BeginXXX/EndXXX pair?
IMHO a synchronous XXX method implementation will always return an answer that
needs to be handled somewhere. Does it happen on client or server
side in my case when I fail to call EndXXX?
Is using the WaitHandles a good and most efficient way of waiting for the fastest result?
If I have to call EndXXX for each BeginXXX I have sent out makes things quite awkward. I would have to delegate the uninteresting EndXXX call into another thread that would just ignore the results. Calling all EndXXX calls in my original thread would defeat the purpose of getting hold of and using the faster answer in a synchronous manner.
The documentation says that you have to call the end method. If you violate what the docs demand you are in undefined behavior land. Resources can leak. Maybe they just do so under load, who knows?
I don't know, sorry. I'm giving a partial answer. My suggestion: Implement a service method that does nothing and invoke it 10M times in a loop. Do resources leak? If yes, you have your answer.
No, Server and client are independent. The server can be sync, the client async or vice versa. Both cannot even tell the difference of what the other does. The two services are separated by TCP and a well-defined protocol. It is impossible for a client to even know what the server does. The server does not even have to use .NET.
I'm not sure what you're asking. Under the hood, WCF clients use TCP. Incoming data will be handled "somewhere" (in practice on the thread-pool).
If your code is fundamentally synchronous, this is the best you can do. You'll burn one thread waiting for N asynchronous service calls. That's ok.
Why don't you just specify a callback in BeginXXX that does nothing else but call EndXXX? That way you always call EndXXX and conform to how the framework is meant to be used. You can still use wait handles.
Depends on the object you call the begin/end pattern on. some are known to leak. from CLR via C# by Jeffrey Richter:
You must call Endxxx or you will leak resources. CLR allocates some
internal resources when you initiate asynchronous operation. If Endxxx
is never called, these resources will be reclaimed only when the
process terminates.
AFAIK the Task-based pattern uses the thread pool to handle its work.
My client makes thousands of calls per second and would completely
trash the thread pool.
It would be so if you used Task.Run or Task.Factory.StartNew. By itself, Task.Factory.FromAsync doesn't create or switch threads explicitly.
Back to your scenatio:
I want to use only the reply from the service that answers faster,
i.e. when WaitHandle.WaitAny returns with an index I only call EndXXX
with the corresponding IAsyncResult to get the faster result. I don't
ever call the other EndXXX.
Let's create the Task wrapper for BeginXXX/EndXXX asynchronous service call:
public static class WcfExt
{
public static Task<object> WorkAsync(this IService service, object arg)
{
return Task.Factory.FromAsync(
(asyncCallback, asyncState) =>
service.BeginWork(arg, asyncCallback, asyncState),
(asyncResult) =>
service.EndWork(asyncResult), null);
}
}
And implement the whatever-service-answers-faster logic:
static async Task<object> CallBothServicesAsync(
IService service1, IService service2, object arg)
{
var task1 = service1.WorkAsync(arg);
var task2 = service2.WorkAsync(arg);
var resultTask = await Task.WhenAny(task1, task2).ConfigureAwait(false);
return resultTask.Result;
}
So far, there has been no blocking code and we still don't create new threads explicitly. The WorkAsync wrapper passes a continuation callback to BeginWork. This callback will be called by the service when the operation started by BeginWork has finished.
It will be called on whatever thread happened to serve the completion of such operation. Most often, this is a random IOCP (input/output completion port) thread from the thread pool. For more details, check Stephen Cleary's "There Is No Thread". The completion callback will automatically call EndWork to finalize the operation and retrieve its result, so the service won't leak resources, and store the result inside the Task<object> instance (returned by WorkAsync).
Then, your code after await Task.WhenAny will continue executing on that particular thread. So, there may be a thread switch after await, but it naturally uses the IOCP thread where the asynchronous operation has completed.
You almost never need to use low-level synchronization primitives like manual reset events with Task Parallel Library. E.g., if you need to wait on the result of CallBothServicesAsync, you'd simple do:
var result = CallBothServicesAsync(service1, service2).Result;
Console.WriteLine("Result: " + result);
Which is the same as:
var task = CallBothServicesAsync(service1, service2);
task.Wait();
Console.WriteLine("Result: " + task.result);
This code would block the current thread, similarly to what WaitHandle.WaitAny does in your original scenario.
Now, blocking like this is not recommended either, as you'd loose the advantage of the asynchronous programming model and hurt the scalability of your app. The blocked thread could be doing some other useful work rather than waiting, e.g., in case with a web app, it could be serving another incoming client-side request.
Ideally, your logic should be "async all the way", up to some root entry point. E.g., with a console app:
static async Task CoreLoopAsync(CancellationToken token)
{
using(var service1 = CreateWcfClientProxy())
using(var service2 = CreateWcfClientProxy())
{
while (true)
{
token.ThrowIfCancellationRequested();
var result = await CallBothServicesAsync("data");
Console.WriteLine("Result: " + result);
}
}
}
static void Main()
{
var cts = CancellationTokenSource(10000); // cancel in 10s
try
{
// block at the "root" level, i.e. inside Main
CoreLoopAsync(cts.Token).Wait();
}
catch (Exception ex)
{
while (ex is AggregatedException)
ex = ex.InnerException;
// report the error
Console.WriteLine(ex.Message);
}
}

Preventing task from running on certain thread

I have been struggling a bit with some async await stuff. I am using RabbitMQ for sending/receiving messages between some programs.
As a bit of background, the RabbitMQ client uses 3 or so threads that I can see: A connection thread and two heartbeat threads. Whenever a message is received via TCP, the connection thread handles it and calls a callback which I have supplied via an interface. The documentation says that it is best to avoid doing lots of work during this call since its done on the same thread as the connection and things need to continue on. They supply a QueueingBasicConsumer which has a blocking 'Dequeue' method which is used to wait for a message to be received.
I wanted my consumers to be able to actually release their thread context during this waiting time so somebody else could do some work, so I decided to use async/await tasks. I wrote an AwaitableBasicConsumer class which uses TaskCompletionSources in the following fashion:
I have an awaitable Dequeue method:
public Task<RabbitMQ.Client.Events.BasicDeliverEventArgs> DequeueAsync(CancellationToken cancellationToken)
{
//we are enqueueing a TCS. This is a "read"
rwLock.EnterReadLock();
try
{
TaskCompletionSource<RabbitMQ.Client.Events.BasicDeliverEventArgs> tcs = new TaskCompletionSource<RabbitMQ.Client.Events.BasicDeliverEventArgs>();
//if we are cancelled before we finish, this will cause the tcs to become cancelled
cancellationToken.Register(() =>
{
tcs.TrySetCanceled();
});
//if there is something in the undelivered queue, the task will be immediately completed
//otherwise, we queue the task into deliveryTCS
if (!TryDeliverUndelivered(tcs))
deliveryTCS.Enqueue(tcs);
}
return tcs.Task;
}
finally
{
rwLock.ExitReadLock();
}
}
The callback which the rabbitmq client calls fulfills the tasks: This is called from the context of the AMQP Connection thread
public void HandleBasicDeliver(string consumerTag, ulong deliveryTag, bool redelivered, string exchange, string routingKey, RabbitMQ.Client.IBasicProperties properties, byte[] body)
{
//we want nothing added while we remove. We also block until everybody is done.
rwLock.EnterWriteLock();
try
{
RabbitMQ.Client.Events.BasicDeliverEventArgs e = new RabbitMQ.Client.Events.BasicDeliverEventArgs(consumerTag, deliveryTag, redelivered, exchange, routingKey, properties, body);
bool sent = false;
TaskCompletionSource<RabbitMQ.Client.Events.BasicDeliverEventArgs> tcs;
while (deliveryTCS.TryDequeue(out tcs))
{
//once we manage to actually set somebody's result, we are done with handling this
if (tcs.TrySetResult(e))
{
sent = true;
break;
}
}
//if nothing was sent, we queue up what we got so that somebody can get it later.
/**
* Without the rwlock, this logic would cause concurrency problems in the case where after the while block completes without sending, somebody enqueues themselves. They would get the
* next message and the person who enqueues after them would get the message received now. Locking prevents that from happening since nobody can add to the queue while we are
* doing our thing here.
*/
if (!sent)
{
undelivered.Enqueue(e);
}
}
finally
{
rwLock.ExitWriteLock();
}
}
rwLock is a ReaderWriterLockSlim. The two queues (deliveryTCS and undelivered) are ConcurrentQueues.
The problem:
Every once in a while, the method that awaits the dequeue method throws an exception. This would not normally be an issue since that method is also async and so it enters the "Exception" completion state that tasks enter. The problem comes in the situation where the task that calls DequeueAsync is resumed after the await on the AMQP Connection thread that the RabbitMQ client creates. Normally I have seen tasks resume onto the main thread or one of the worker threads floating around. However, when it resumes onto the AMQP thread and an exception is thrown, everything stalls. The task does not enter its "Exception state" and the AMQP Connection thread is left saying that it is executing the method that had the exception occur.
My main confusion here is why this doesn't work:
var task = c.RunAsync(); //<-- This method awaits the DequeueAsync and throws an exception afterwards
ConsumerTaskState state = new ConsumerTaskState()
{
Connection = connection,
CancellationToken = cancellationToken
};
//if there is a problem, we execute our faulted method
//PROBLEM: If task fails when its resumed onto the AMQP thread, this method is never called
task.ContinueWith(this.OnFaulted, state, TaskContinuationOptions.OnlyOnFaulted);
Here is the RunAsync method, set up for the test:
public async Task RunAsync()
{
using (var channel = this.Connection.CreateModel())
{
...
AwaitableBasicConsumer consumer = new AwaitableBasicConsumer(channel);
var result = consumer.DequeueAsync(this.CancellationToken);
//wait until we find something to eat
await result;
throw new NotImplementeException(); //<-- the test exception. Normally this causes OnFaulted to be called, but sometimes, it stalls
...
} //<-- This is where the debugger says the thread is sitting at when I find it in the stalled state
}
Reading what I have written, I see that I may not have explained my problem very well. If clarification is needed, just ask.
My solutions that I have come up with are as follows:
Remove all Async/Await code and just use straight up threads and block. Performance will be decreased, but at least it won't stall sometimes
Somehow exempt the AMQP threads from being used for resuming tasks. I assume that they were sleeping or something and then the default TaskScheduler decided to use them. If I could find a way to tell the task scheduler that those threads are off limits, that would be great.
Does anyone have an explanation for why this is happening or any suggestions to solving this? Right now I am removing the async code just so that the program is reliable, but I really want to understand what is going on here.
I first recommend that you read my async intro, which explains in precise terms how await will capture a context and use that to resume execution. In short, it will capture the current SynchronizationContext (or the current TaskScheduler if SynchronizationContext.Current is null).
The other important detail is that async continuations are scheduled with TaskContinuationOptions.ExecuteSynchronously (as #svick pointed out in a comment). I have a blog post about this but AFAIK it is not officially documented anywhere. This detail does make writing an async producer/consumer queue difficult.
The reason await isn't "switching back to the original context" is (probably) because the RabbitMQ threads don't have a SynchronizationContext or TaskScheduler - thus, the continuation is executed directly when you call TrySetResult because those threads look just like regular thread pool threads.
BTW, reading through your code, I suspect your use of a reader/writer lock and concurrent queues are incorrect. I can't be sure without seeing the whole code, but that's my impression.
I strongly recommend you use an existing async queue and build a consumer around that (in other words, let someone else do the hard part :). The BufferBlock<T> type in TPL Dataflow can act as an async queue; that would be my first recommendation if you have Dataflow available on your platform. Otherwise, I have an AsyncProducerConsumerQueue type in my AsyncEx library, or you could write your own (as I describe on my blog).
Here's an example using BufferBlock<T>:
private readonly BufferBlock<RabbitMQ.Client.Events.BasicDeliverEventArgs> _queue = new BufferBlock<RabbitMQ.Client.Events.BasicDeliverEventArgs>();
public void HandleBasicDeliver(string consumerTag, ulong deliveryTag, bool redelivered, string exchange, string routingKey, RabbitMQ.Client.IBasicProperties properties, byte[] body)
{
RabbitMQ.Client.Events.BasicDeliverEventArgs e = new RabbitMQ.Client.Events.BasicDeliverEventArgs(consumerTag, deliveryTag, redelivered, exchange, routingKey, properties, body);
_queue.Post(e);
}
public Task<RabbitMQ.Client.Events.BasicDeliverEventArgs> DequeueAsync(CancellationToken cancellationToken)
{
return _queue.ReceiveAsync(cancellationToken);
}
In this example, I'm keeping your DequeueAsync API. However, once you start using TPL Dataflow, consider using it elsewhere as well. When you need a queue like this, it's common to find other parts of your code that would also benefit from a dataflow approach. E.g., instead of having a bunch of methods calling DequeueAsync, you could link your BufferBlock to an ActionBlock.

HttpWebRequest.BeginGetResponse

I need to make async request to web resource and use example from this page (link to full example):
HttpWebRequest myHttpWebRequest= (HttpWebRequest)WebRequest.Create("http://www.contoso.com");
RequestState myRequestState = new RequestState();
myRequestState.request = myHttpWebRequest;
// Start the asynchronous request.
IAsyncResult result=
(IAsyncResult) myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallback),myRequestState);
But when I am testing the application the execution freeze(on 2-3 sec) on the last line of this code (i can watch it using debugger).
Why? Is it my mistake or it is a standard behaviour of the function?
You can try, I m sure thats better
private void StartWebRequest(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.BeginGetResponse(new AsyncCallback(FinishWebRequest), request);
}
private void FinishWebRequest(IAsyncResult result)
{
HttpWebResponse response = (result.AsyncState as HttpWebRequest).EndGetResponse(result) as HttpWebResponse;
}
Because of chross thread of textbox'value,But this is wpf application i will retag this, btw you can use webclient like
private void tbWord_TextChanged(object sender, TextChangedEventArgs e)
{
WebClient wc = new WebClient();
wc.DownloadStringCompleted += HttpsCompleted;
wc.DownloadStringAsync(new Uri("http://en.wikipedia.org/w/api.php?action=opensearch&search=" + tbWord.Text));
}
private void HttpsCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
//do what ever
//with using e.Result
}
}
It's the standard behaviour.
From the documentation on HttpWebRequest.BeginGetResponse Method:
The BeginGetResponse method requires some synchronous setup tasks to complete (DNS resolution, proxy detection, and TCP socket connection, for example) before this method becomes asynchronous. [...]
it might take considerable time (up to several minutes depending on network settings) to complete the initial synchronous setup tasks before an exception for an error is thrown or the method succeeds.
To avoid waiting for the setup, you can use
HttpWebRequest.BeginGetRequestStream Method
but be aware that:
Your application cannot mix synchronous and asynchronous methods for a particular request. If you call the BeginGetRequestStream method, you must use the BeginGetResponse method to retrieve the response.
The response occurs on a separate thread. Winforms are not multi-thread safe, so you're going to have to dispatch the call on the same thread as the form.
You can do this using the internal message loop of the window. Fortunately, .NET provides a way to do this. You can use the control's Invoke or BeginInvoke methods to do this. The former blocks the current thread until the UI thread completes the invoked method. The later does so asynchronously. Unless there is cleanup to do, you can use the latter in order to "fire and forget"
For this to work either way, you'll need to create a method that gets invoked by BeginInvoke, and you'll need a delegate to point to that method.
See Control.Invoke and Control.BeginInvoke in the MSDN for more details.
There's a sample at this link: https://msdn.microsoft.com/en-us/library/zyzhdc6b(v=vs.110).aspx
Update: As I'm browsing my profile because I forgot i had an account here - i noticed this and I should add: Anything past 3.5 or when they significantly changed the asynchronous threading model here is out of my wheelhouse. I'm out professionally, and while I still love the craft, I don't follow every advancement. What I can tell you is this should work in all versions of .NET but it may not be the absolute pinnacle of performance 4.0 and beyond or on Mono/Winforms-emulation if that's still around. On the bright side, any hit usually won't be bad outside server apps, and even inside if the threadpool is doing its job. So don't focus optimization efforts here in most cases, and it's more likely to work on "stripped down" platforms you see running things like C# mobile packages although I'd have to look to be sure and most don't run winforms but some spin message loops and this works there too. Basically to bottom line, it's not the "best answer" for the newest platforms in every last case. But it might be more portable in the right case. If that helps one person avoid making a design error, then it was worth the time I took to write this. =)
You can use BackgroundWorker add do the whole thing in DoWork

Can a standard thread be reused for the Thread Pool?

I'm having some weird behavior in an application which is puzzling me.
I create a thread, let's call it worker, which is responsible for handling communication requests. Clients write on a pipe while the thread consumes the requests and send messages.
Now, the main loop of the thread has something like this:
lock(this)
{
object_id = Transport.BeginSend(xxx, xxx, callback, yyy)
clientsObjects[object_id] = client_id;
}
now the callback needs to access the client_id (its a bit more complicated than what I wrote, but the thing is that the callback receives the object_id, just assume BeginSend is a call to UdpClient.BeginSend
void Callback(IAsyncResult ar)
{
State st = (State)ar;
lock(this)
{
client_id = clientsObjects[st.object_id]
}
}
Locks are there because the callback may fire so fast that it actually happens before clientsObjects[object_id] = client_id; can execute...
Ok, now.. the problem is it's not working, well it works now and then... why? If I trace the ManagedThreadIds of the threads which are executing the BeginSend and the one that is executing the callback I find that sometimes, they have the same ThreadId!!
Is that possible? How can that happen? Any suggestions about what am I doing wrong?
Comment: Actual code is not exactly like that, Transport is a wrapper around the UDPClient which allows changing the transport layer easily, locks aren't really locks but spinlocks ... but the concept itself is more or less what I've written down.
Here is an older article that talks about the Stream.BeginRead() function actually operating synchronously, not asynchronously as you would expect. The article is from 2004, so I'm assuming it's referring to .NET 1.0/1.1. The article does not specifically refer to UdpClient.BeginSend(), but I've often wondered if the BeginXXX functions in the Socket stuff have the same behavior at times, especially if there is data to be read immediately. It might be worth checking the web to see if this is a possibility.
Is it possible to pass the client_id to the callback function via the state parameter of the BeginSend() function?
object_id = Transport.BeginSend(xxx, xxx, Callback, client_id);

Categories