AsyncCallBack CompletedSynchronously - c#

I've noticed the following pattern recently, but I don't entirely grasp the usage of the CompletedSynchronously property:
IAsyncResult channelOpenResult = channel.BeginOpen(new AsyncCallback(OnOpenCompleteChannel), channel);
if (channelOpenResult.CompletedSynchronously)
{
CompleteOpenChannel(channelOpenResult);
}
And then again, in the callback:
void OnOpenCompleteChannel(IAsyncResult result)
{
if (result.CompletedSynchronously)
return;
else
CompleteOpenChannel(result);
}
And somewhere in the code there is of course a function:
void CompleteOpenChannel(IAsyncResult result) ...
Is this a way to handle the asynchronous call differently depending on whether it completes directly or not? But why use it in this case, since the AsyncCallback always will be called (will it?)?
Could someone give an example where the call is made synchronously?

See this blog. A common pattern does async work in a loop, and checking CompletedSynchronously helps avoid the case where you get 'unlucky' and a bunch of async calls happen to complete sync and you risk StackOverflowException. (E.g. if you're reading data over the network, and the data you're reading has already come over the wire and is buffered, your async call may complete synchronously, which means your callback is called on the same thread (with a taller stack), which means you better not schedule another async call in a loop.)

According to this document you can supply the call with a synchronous and ASync callback, and only if the call was not handled synchronously, will it call the ASync methods. I do not think this is really applicable to Silverlight (because all Silverlight calls are ASync to a degree) but is probably used more for custom factories in other .NET applications.
Hope this helps.

Related

Async not working as I expected

I've read all I can find on async programming in asp.net (c#). I've made sense of most of how it's supposed to work and when it should be used. Yet I find basic examples not working as I expect. Without Task.Run it doesn't seem to actually run asynchronously.
Can someone tell me what I'm missing in this example?
Say the code is like so
public async Task SubTask2()
{
LongRunningOperation2();
Response.Write("<br>------------------------ Finished -------------------------<br>");
}
private async Task<Boolean> LongRunningOperation1()
{
int counter;
for (counter = 0; counter < 50000; counter++)
{
Response.Write(counter + "<br>");
}
return await Task.FromResult<bool>(true);
}
private async Task<Boolean> LongRunningOperation2()
{
await LongRunningOperation1();
Response.Write("<br>------------------------ Long Task -------------------------<br>");
return true;
}
Shouldn't LongRunningOperation2() return to SubTask2() and print "finished" before or while writing out numbers? Instead it prints finished at the end. Using Task.Run works as expected but then I don't see the point of ever not using Task.Run
A design consideration of the async/await pattern is that sometimes code that has an async signature might return synchronously (immediately) - perhaps due to caching or local data buffering (reading data from a socket, perhaps, and having spare data left to consume from the buffer), or perhaps due to IoC etc providing a synchronous implementation of an asynchronous signature. In that scenario, the entire engine is designed to optimize by not doing anything as callbacks, but continuing to run synchronously. This is not an edge-case - recent C# updates have extended this by adding support for custom awaitables (in particular: ValueTask<T>) to make this even more efficient in the case when something completes with a synchronous but non-trivial result.
The purpose of async is to facilitate scenarios that have genuinely async components, freeing up the thread to do more useful things than waiting for an async operation to complete. It is not about parallelization.
In your case, all of your code is actually synchronous, so it continues to run synchronously all the way through.
First, you're missing await in SubTask2(), so it actually runs synchronously (waits for LongRunningOperation2() to finish).
Secondly, even with asynchronous execution, "finished" wouldn't be printed before LongRunningOperation2() finished it's work. The point of using it is to free the thread, so it can do some other work in the meantime (e.g. handle another request).

System.ObjectDisposedException after converting methods to async [duplicate]

I want to send a message using an asynchronous call but disposable resources are used in the process. I'm not sure how to properly handle this.
using(IDisposable disposeMe = new DisposableThing())
{
MethodAsync(disposeMe);
}
Any ideas how to do this. The async method does not have any callback.
EDIT:
Based on the suggestion the accepted answer by #Servy. The implementation was changed to:
public async Task Method()
{
using(IDisposable disposeMe = new DisposableThing())
{
await MethodAsync(disposeMe);
}
}
The async method does not have any callback
Well that's a problem. A very big problem. If at all possible you should fix that; unless there is a very good reason not to, all asynchronous methods should provide some means for the caller to know when they have completed, whether it's a callback, returning a Task, firing an event, etc. It's particularly troubling for an asynchronous method that is dependent on a disposable resource to do this.
If you really do have no way of being notified when the operation completes, then there is no way for you to call Dispose after the method completes. The only means you have of ensuring you don't dispose of the resource while the async operation still needs it is to leak the resource and not dispose of it at all. If the disposable resource has a finalizer it's possible it will be cleaned up eventually, but not all disposable resources do so.
If you can modify the asynchronous method somehow then you simply need to call Dispose in the callback, or in a continuation of the task, or in a handler of the relevant event. You won't be able to use a using unless you can await the asynchronous operation (because await is just awesome like that).

Calling asynchronous method in using statement

I want to send a message using an asynchronous call but disposable resources are used in the process. I'm not sure how to properly handle this.
using(IDisposable disposeMe = new DisposableThing())
{
MethodAsync(disposeMe);
}
Any ideas how to do this. The async method does not have any callback.
EDIT:
Based on the suggestion the accepted answer by #Servy. The implementation was changed to:
public async Task Method()
{
using(IDisposable disposeMe = new DisposableThing())
{
await MethodAsync(disposeMe);
}
}
The async method does not have any callback
Well that's a problem. A very big problem. If at all possible you should fix that; unless there is a very good reason not to, all asynchronous methods should provide some means for the caller to know when they have completed, whether it's a callback, returning a Task, firing an event, etc. It's particularly troubling for an asynchronous method that is dependent on a disposable resource to do this.
If you really do have no way of being notified when the operation completes, then there is no way for you to call Dispose after the method completes. The only means you have of ensuring you don't dispose of the resource while the async operation still needs it is to leak the resource and not dispose of it at all. If the disposable resource has a finalizer it's possible it will be cleaned up eventually, but not all disposable resources do so.
If you can modify the asynchronous method somehow then you simply need to call Dispose in the callback, or in a continuation of the task, or in a handler of the relevant event. You won't be able to use a using unless you can await the asynchronous operation (because await is just awesome like that).

Truly asynchronous WCF service

I am implementing an asynchronous service. After evaluating Microsoft's example, I am wondering if their approach is truly asynchronous. I am pretty sure it is, but some of the samples I've seen online and the AsyncCallback parameter causes me to wonder.
According to the example, we need to implement the Begin and End method pair like this:
public IAsyncResult BeginGetAcmeAnvil(AsyncCallback callback, object state)
{
// Starts synchronous task
var acmeAsyncResult = new AcmeAsyncResult<Anvil>
{
Data = new Anvil()
};
return acmeAsyncResult;
}
public Anvil EndGetAcmeAnvil(IAsyncResult result)
{
var acmeAsyncResult = result as AcmeAsyncResult<Anvil>;
return acmeAsyncResult != null
? acmeAsyncResult.Data
: new Anvil();
}
Pretty straightforward, but why do we have an AsyncCallback parameter? Shouldn't we do a call to callback which will in turn trigger the End method?
This is what I have in mind:
public delegate void AsyncMethodCaller(AcmeAsyncResult<Anvil> acmeAsyncResult,
AsyncCallback callback);
public IAsyncResult BeginGetAcmeAnvil(AsyncCallback callback, object state)
{
var acmeAsyncResult = new AcmeAsyncResult<Anvil>();
var asyncMethodCaller = new AsyncMethodCaller(GetAnvilAsync);
// Starts asynchronous task
asyncMethodCaller.BeginInvoke(acmeAsyncResult, callback, null, null);
return acmeAsyncResult;
}
private void GetAcmeAnvilAsync(AcmeAsyncResult<Anvil> acmeAsyncResult,
AsyncCallback callback)
{
acmeAsyncResult.Data = new Anvil();
callback(acmeAsyncResult); // Triggers EndGetAcmeAnvil
}
public Anvil EndGetAcmeAnvil(IAsyncResult result)
{
var acmeAsyncResult = result as AcmeAsyncResult<Anvil>;
return acmeAsyncResult != null
? acmeAsyncResult.Data
: new Anvil();
}
I did some load testing using loadUI, but there was no obvious performance changes.
I found a good article explaining how to get the best performance out of your Async WCF service.
The gist is:
don't do heavy work in the Begin method, and
do make the callback to trigger the End method.
Here's an extract from the text:
For best performance, here are two principles when you call/implement the above asynchronous pattern:
Principle 1: Do not do heavy-weighted work inside the Begin method...
The reason for this is that you should return the calling thread as soon as possible so that the caller can schedule other work. If it’s a UI thread, the application needs to use the thread to respond to user inputs. You should always put heavy operations in a different thread if possible.
Principle 2: Avoid calling End method on the same thread of the Begin method.
The End method is normally blocking. It waits for the operation to complete. If you implement the End method, you would see that it actually calls IAsyncResult.WaitHandle.WaitOne(). On the other hand, as a normal implementation, this WaitHandle is a delay allocated ManualResetEvent. As long as you don’t call it, it would be not allocated at all. For fast operations, this is pretty cheap. However, once End is called, you would have to allocate it. The right place to call End is from the callback of the operation. When the callback is invoked, it means that the blocking work is really completed. At this point, you can call End to get data retrieved without sacrificing performance.
I think the main reason its separated like this is that the WCF runtime is handling the thread synchronization as opposed to you having to handle it manually.
If you were invoking the end method via callback, you would have to handle the synchronization which makes the pattern quite a bit more complex (as you can see in your coding examples). The goal of this pattern is not for you to really be aware of the threading stuff, you just want to code your long running operation without having to think about the implementation details of the threading.

Do asynchronous web service calls always call the AsyncCallback?

I'm making asynchronous web service calls from a C# app:
{
//Put UI in 'loading' state
...
//Now call web service
webServiceProxy.BeginMyMethod(param, new AsyncCallback(MyCallback), null);
}
private void MyCallback(IAsyncResult res)
{
...
//process result
// Put UI back in normal state (yes I'm marshalling back to the UI thread)
}
The main thread puts the app in a "waiting" mode, and then the end of the Callback function re-enables the controls. I'm seeing a bug that occasionally, the UI is stuck forever in the loading mode.
Now there may just be a bug in the callback code (there's quite a bit there), but my question to the community here is this:
Is "MyCallback" GUARANTEED to be called? Presuming that "BeginMyMethod" didn't throw an exception, can I be sure that MyCallback will be executed? I'm seeing a "CompletedSynchronously" and "IsCompleted" on the IAsyncResult returned by the BeginXXX functions, but I'm not sure if that's important or not.
Yes, the callback is guaranteed to be called. The callback is what permits asynchronous code using the Begin* / End* pattern to be written in a continuation-passing style.
You must call the corresponding End* method in your callback (normally, the first thing in the callback), however. It is how the asynchronous method signals an exception that may have occurred during the call, for one thing, as well as the way to get a result out (if any).
Coding the asynchronous pattern using anonymous delegates when using C# 2.0 is sometimes more elegant, and permits writing of the post-call continuation close to the initiation of the call, as well as permitting much easier data sharing through captured variables, providing that appropriate synchronization measures are used.
Ref: http://msdn.microsoft.com/en-us/library/ms228972.aspx:
Applications that can do other work while waiting for the results of an asynchronous operation should not block waiting until the operation completes. Use one of the following options to continue executing instructions while waiting for an asynchronous operation to complete:
Use an AsyncCallback delegate to process the results of the asynchronous operation in a separate thread. This approach is demonstrated in this topic.
[...]
The AsyncCallback will be called regardless of whether the operation was completed synchronously or asynchronously.
I believe the callback is not guaranteed to be called if the CompletedSynchronously property is true.

Categories

Resources