How do I create a naturally asynchronous method when inside calls are not naturally asynchronous?
.net, async-await, asynchronous, c#, dotnet-httpclient
Solution
`HttpClient.GetStreamAsync` is a pure asynchronous method, which means no new threads will be introduced while making the call, and when using in combination with `await`, will yield control back to the caller until the IO request is done. This will scale well, as you actually free the ThreadPool thread that invoked the operation to so more work while the request is executing, so your server can actually process more requests in the meantime.
On the contrary, using a dedicated thread (sync over async) just to make a blocking IO request call will definitely not scale well, and might eventually cause a starvation if the execution time is long enough.
Edit
The truely asynchronous nature of the `XXXAsync` implementation comes from the network device driver supplying an asynchronous endpoint to the OS. Under the covers the `WinHTTP` (Thanks @Noseratio for the correction) library is used for the async operations. What that means is that an I/O Request Packet (IRP) is generated and passed to the device driver. Once the request is complete, a CPU interrupt will occur which will eventually cause the callback registered to be invoked. You can look at theses examples: Using WinInet HTTP functions in Full Asynchronous Mode or Windows with C++ - Asynchronous WinHTTP for asynchronous examples, and of course read the excellent There Is No Thread by Stephan Cleary. You can natively implement it yourself and wrap it in a managed wrapper.
Problem
In this scenario, system A needs to send a message to system B. The following code shows a sample of how this was accomplished: ``` public interface IExecutionStrategy { Task<Result> ExecuteMessage(Message message); } public class WcfExecutionStrategy { public async Task<Result> ExecuteMessage(Message message) { using (var client = new Client()) { return await client.RunMessageOnServer(message); } } } public class MessageExecutor { private readonly IExecutionStrategy _strategy; public MessageExecutor(IExecutionStrategy strategy) { _strategy = strategy; } public Task<Result> ExecuteMessage(Message msg) { // .... // Do some common checks and code here // .... var result = await _strategy.ExecuteMessage(msg); // .... // Do some common cleanup and logging here // ..... return result; } } ``` For reasons out of scope of this question we decided to switch from Wcf to using raw http streams, but we needed both side by side to gather metrics and test it out. So I created a new `IExecutionStrategy` implementation to handle this: ``` public class HttpclientExecutionStrategy { public async Task<Result> ExecuteMessage(Message message) { var request = CreateWebRequestmessage var responseStream = await Task.Run(() => { var webResponse = (HttpWebResponse)webRequest.GetResponse(); return webResponse.GetResponseStream(); } return MessageStreamer.ReadResultFromStream(responseStream); } } ``` Essentially, the only way I could get this to be asynchronous was to wrap it in a `Task.Run()` so the web request was none blocking. (Note: due to unique stream manipulation requirements on both sending and receiving it is not straight forward to implement this is in `HttpClient`, and even if it's possible this fact is out of scope for this question). We thought this was fine until we read Stephen Cleary's multiple blog posts about how `Task.Run()` is bad, both in library code and in Asp.Net applications. This makes perfect sense to me. What doesn't make sense is how you actually implement a naturally asynchronous call if the third party library does not support an asynchronous movement. For example, if you were to use `HttpClient.GetStreamAsync()` what does that do that makes it better for asynchronous operations than `Task.Run(() => HttpClient.GetStream())`, and is there any way to remedy this for non-async third party libraries?