I have some C# code that Im actually porting to VB.Net. Now I noticed ConfigureAwait(false) is used everywhere. A requirement is that the code be dependant on .Net 4.0
As you might know... ConfigureAwait(false) appears in .Net 4.5. How would I convert the following code to be compliant with .Net 4.0?
Is there a generic solution as ConfigureAwait occurs everywhere in the code
public async Task<ListResponse> GetResponseAsync(ListRequest request = null)
{
request = request ?? new ListRequest
{
Limit = _limit
};
using (var client = CreateMailClient("lists"))
{
var response = await client.GetAsync(request.ToQueryString()).ConfigureAwait(false);
await response.EnsureSuccessMailChimpAsync().ConfigureAwait(false);
var listResponse = await response.Content.ReadAsAsync<ListResponse>().ConfigureAwait(false);
return listResponse;
}
}
ANSWER:
Reference Microsoft.BCL.Async
This is what you are looking for to be precise.
If you are using ConfigureAwait(), you probably really care about it and want it to actually work. Unfortunately, because async methods might actually complete synchronously, the call to ConfigureAwait() might not affect anything. That means you have to put it on the next async call too, and so on, until it is on every single method in your library.
Reference Microsoft Developers
Alternatives to Configure await
Sample code
Related
I am writing a class library wrapper for a 3rd party API, using .Net Standard and later on I'm planning to use this wrapper in my other project. While looking around the web, I've found out that general concern is that one should use HttpClient class for making HTTP requests.
I am aware of two approaches that I could take:
Using async/await all the way down to the client project
Using Task.Wait() method
So far I am going for the 1st approach. But both approaches seem rather problematic. First one would be less reusable than having synchronous methods, which return their type and not a Task object. I'd rather take the second approach, but it's prone to deadlocks.
My code for making a single request (HttpClient initialized with parameterless constructor):
protected async Task<JObject> Request(string url)
{
Uri uri = BuildUrl(url);
HttpResponseMessage response = await HttpClient.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
string result = await response.Content.ReadAsStringAsync();
return JObject.Parse(result);
}
return new JObject();
}
For multiple requests:
protected async Task<JObject[]> Request(IEnumerable<string> urls)
{
var requests = urls.Select(Request);
return await Task.WhenAll(requests);
}
And usage in the wrapper class:
protected async Task<JObject> RequestGet(string id, bool byUrl)
{
if (IsBulk && !byUrl)
return await Request($"{Url}?id={id}");
if (byUrl)
return await Request(Url + id);
return await Request(Url);
}
How could I modify the code (1st and 2nd snippet) so that it wouldn't cause any deadlocks and async usage in every caller method (3rd snippet)?
Using HttpClient synchronously is unsupported and deadlock prone, and there's nothing you can do (including using Task.Wait) to change that fact. You have 2 options:
Support async only.
Use the older WebRequest APIs instead and support synchronous calls that way.
I would opt for option 1. There's a reason that the latest and greatest HTTP libraries don't even support synchronous I/O anymore. The newer wave of multi-core processors and distributed architectures have triggered a paradigm shift in the programming world, where tying up threads while waiting on I/O (especially longer-running network calls like HTTP) is a total waste of resources. And when languages like C# provide incredible support for async programming out of the box, there's virtually no good reason to do synchronous HTTP anymore. Most developers understand this I don't think you should be concerned about abandoning users by going async only. Instead, encourage them to get up to speed on doing it the right way.
Using async all the way down is the right way, and you can return results from a Task method (in other words -- as your own code shows -- it isn't right to say they don't return anything other than Task):
public async Task<string> GetString(int value)
{
return value.ToString();
}
Obviously that doesn't need to be async, it doesn't need to await anything, but the point is Task can return anything thanks to generics. You can even use the fancy new C# 7 value-tuples:
public async Task<(string name, int age)> GetUserInfo(int userId) { ... }
I'm pretty new to working with HTTP stuff so I'm rather confused as to what would be the best approach to request data from a HTTP address every few seconds or so.
The API I'm using has - at least to my knowledge no webhook support. So I imagine the way to update my data would be a rather crude way of doing so.
I want this to happen in the background so the GUI does not freeze and become unresponsive. So I know I (probably) need to fiddle with threads.
Best results I've had has been with a async/await Timer. I'm not entirely sure how to work with this and the only way for me to get it to work is to throw an exception after it has elapsed. If I don't - it says that not all nodes return a value and I can't even use return which really, really confuses me.
How should I be doing this?
If it's of any use, I'm working on creating my own RCON tool for a game which has all kinds of server data available via a HTTP API - but documentation for this API is very lackluster.
if you go to .net core you can see my previous answer on: Start multiple background threads inside Self Hosted ASP.NET Core Microservice
for .net framework you have to do a little more yourself. But still very do-able!
in your global.asax you have (or should I say: should) have your dependency injection. Something like:
protected void Application_Start()
{
Bootstrap();
//and do something more
}
private static void Bootstrap()
{
var container = new Container();
container.Register(() => new HttpClient());
container.RegisterSingleton<IApiCaller, ApiCaller>();
container.RegisterInitializer<IApiCaller>(ApiCaller=> apicaller.StartCallingAsync());
// Suppress warnings for HttpClient
var registration = container.GetRegistration(typeof(HttpClient)).Registration;
registration.SuppressDiagnosticWarning(DiagnosticType.DisposableTransientComponent, "Dispose is being called by code.");
registration.SuppressDiagnosticWarning(DiagnosticType.LifestyleMismatch, "Every HttpCient is unique for each dependency.");
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
}
In this case, I let SimpleInjector start my background thread to do a lot of work.
In the apicaller you can do your httpcalls.
something like:
public async Task StartCallingAsync(CancellationToken cancellationToken = (default)CancellationToken)
{
while(true)
{
var response = await _httpClient.GetAsync(url);
if (response.IsSuccessStatusCode)
{
//do work
}
await Task.Delay(10000, cancellationToken);
}
}
for the GetAsync there are extension methods that can cast it directly to your object.
can you work with this?
I m trying to write an async service with ServiceStack and to me it seems that this feature is not really complete.
My questions:
1) How do you pass CancellationTokens in the service methods?
2) What about ConfigureAwait(false) in those methods? For example
public Task<SomeResponse> Get(SomeRequest request)
{
return _manager.ExecuteAsync(request).ConfigureAwait(false);
}
This doesnt compile.
3) Should we be marking such services with the async keyword and return Task to make them awaitable? For example this doesnt work (usage is silly but you get the point)
public async Task<SomeResponse> Get(SomeRequest request)
{
return await _manager.ExecuteAsync(request).ConfigureAwait(false);
}
Should we even be writing async services with ServiceStack? Is there a benefit or the current implementation defeats the purpose?
Thanks
If the methods don't accept cancellation tokens, then they weren't designed to be cancellable, and you can't cancel them.
You're not actually awaiting the task, so there's no await to configure. Just omit the ConfigureAwait since you have no await to configure.
There's no need to mark a method as async if you're not actually going to leverage any of the features of it or accomplish anything with it that isn't already done by just not doing that. It's not breaking anything other than making the code a tiny bit slower, but it's not adding anything either.
You can make an async request as normal using C# async/await, i.e:
var response = await client.GetAsync(requestDto);
Or if you prefer (or cannot use await), you can use Continuations on the returned Task<T>, e.g:
client.GetAsync(new Hello { Name = "World!" })
.Success(r => r => r.Result.Print())
.Error(ex => { throw ex; });
You can cancel an async request with:
client.CancelAsync();
This calls HttpWebRequest.Abort() behind the scenes.
I'm still getting to know the various async features of .NET 4.5, and I've run into something interesting. Given the following in my MVC controller, I get different results when executing (1) and (2)
public ActionResult Index() {
var stuff = SomeExpensiveFunction();
return View(stuff);
}
private byte[] SomeExpensiveFunction() {
string url = "http://some-url.../";
// (1)
var wc = new WebClient();
return wc.DownloadDataTaskAsync(url).Result;
// (2)
var hc = new HttpClient();
return hc.GetAsync(url).Result.Content.ReadAsByteArrayAsync().Result;
}
On the surface, they seem the same - both the WebClient.DownloadDataTaskAsync and HttpClient.GetAsync are async methods which return a Task. The WebClient version returns Task<byte[]> while the HttpClient version returns Task<HttpResponseMessage> which I have to dig the bytes out of, but I'm calling .Result either way, which I would expect to complete prior to leaving the function.
With (1), I get a yellow-screen with An asynchronous operation cannot be started at this time.... With (2), everything works fine.
I can change the whole stack and use an async on the controller method itself and the SomeExpensiveFunction, and everything works fine. But I'm trying to figure out if there's something fundamentally wrong with (1) or with WebClient in general when working with MVC. Any thoughts?
EDIT: I know in this example I can use the synchronous versions of those calls since I'm not really doing anything asynchronously - this is just an example based on a larger codebase.
You've fallen foul of ASP.NET's SynchronizationContext. To make the WebClient example work, you should make the entire controller asynchronous. Try this:
public async Task<ActionResult> IndexAsync() {
string url = "http://some-url.../";
using (var wc = new WebClient())
return View(await wc.DownloadDataTaskAsync(url));
}
See http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4 for a briefing on asynchronous controllers, and http://www.tugberkugurlu.com/archive/asynchronousnet-client-libraries-for-your-http-api-and-awareness-of-async-await-s-bad-effects for an explanation of the deadlocking effect of the async/await pattern.
I'm not 100% sure but this could be due to improper use of Async methods. Perhaps you are seeing this behavior because you are not expected to use Async methods in synchronous fashion by calling Result.
Is it possible to take advantage of async/await on the ServiceStack's server methods? Googling brings up a fork of ServiceStack which seems to do the trick but it hasn't been updated for few months and there is no info if that code has been merged into the current official version (v3.9.32).
I built a simple service using the async / await pattern and it doesn't behave correctly but I wonder if this is just a configuration issue. Here's the code:
public class PodcastService : Service
{
public async Task<object> Get(Podcast request)
{
var client = new WebClient();
var data = await client.DownloadStringTaskAsync("http://www.google.fi");
return new PodcastResponse() { Date = DateTime.Now };
}
}
And here's the JSON the method returns:
{"Result":{"__type":"WebApplication2.PodcastResponse, WebApplication2","Date":"2012-12-10T17:18:32.1653985+02:00"},"Id":1,"Status":"RanToCompletion","IsCanceled":false,"IsCompleted":true,"CreationOptions":0,"IsFaulted":false}
For comparison, here's the same method without any async/await:
public class PodcastService : Service
{
public object Get(Podcast request)
{
return new PodcastResponse() { Date = DateTime.Now };
}
}
And here's the result:
{"Date":"2012-12-10T17:20:23.0245677+02:00"}
Any ideas? Is the fork still the way to go or is the async/await already implemented in ServiceStack but requires some configuration?
You can check the project status here. The async branch is still in the "Doing" phase.
The first result looks like a serialized Task object, so they definitely haven't added async service support yet.
UPDATE
We can forget about the async/await fork as ServiceStack goes commercial and gets a breaking rewrite for v4. The latest available version, v3.9.62 is a feature-freeze version as development switches to v4.