Operational Costs of Using IAsyncResult Overload for Task.FromAsync

I am trying to port some existing APM calls ( BeginX , EndX ) to Tasks in order to get all the useful benefits from them. Unfortunately, our methods are unconventional and use the out parameters and therefore cannot use the standard FromAsync method, where you give it both the start and end delegates and allow it to easily transfer it.

This article describes an alternative: an overload that accepts IAsyncResult and only requires an end callback. They take the IAsyncResult handle, then wait for completion, then call the delegate that you passed.

It seemed fine, but then I read another article on APM call wrapping in tasks . He also mentions that IAsyncResult overloading IAsyncResult not as efficient as other methods. It seems to me that this means that the callback is not used to report the completion of the method. This means that they must use AsyncWaitHandle or IsCompleted . Which one do they use? How high is the performance?

If this is done by polling, it means that the callback may not appear immediately, and they should carefully check it during the whole call. If they have AsyncWaitHandle , they have another thread that sits and waits for the result, which completely hits the point of using the asynchronous method for me.

Does anyone know what they are doing, and how serious is this performance hit?

+6
source share
4 answers

Does anyone know what they are doing, and how serious is this performance hit?

This is not incredibly heavy, but there is more overhead. Since you are not providing them with the same information ( IAsyncResult only), the implementation should call ThreadPool.RegisterWaitForSingleObject to call the callback when IAsyncResult completes.

If this is not used, and there is a Begin / End + callback pair, the callback can automatically initiate the completion of the task, excluding the additional wait call here. This effectively binds the ThreadPool thread to block (WaitOne) on the wait handle until the operation completes. If this is a rare occurrence, the performance overhead is probably negligible, but if you do it a lot, it can be problematic.

+1
source

Looking at the code in JustDecompile, it creates a TaskCompletion object that wraps IAsyncObject, which creates a new task, which probably means a thread waiting for IAsyncObject to complete. Not ideal, but this is probably the only way to do this, since there is no way to do a good survey of all participants.

+1
source

Arrived here because I had a similar problem (with out parameters), but only by the End method. This is what I came up with can help someone:

 var provider = new Provider(); return Task<Whatever>.Factory.FromAsync(provider.Begin, ar => { Whatever outparam; provider.End(out outparam); return outparam; }, state); 

It compiles :)

+1
source

When you pass ISyncResult, TaskFactory will not be able to insert the callback back. Therefore, TaskFactory needs ISynResult to start WaitHandle and needs ThreadPool to get a thread waiting for this handle. No survey.

0
source

Source: https://habr.com/ru/post/890266/


All Articles