I have an IO bound method that hangs for a split second while fetching data. I've attempted to convert the method to an async method but am having issues with this.
I've included below the non-async version of the code, and my attempt at making it async.
//non async method
public double GetBaseline()
{
var Client = new RestClient();
IRestResponse response;
Client.BaseUrl = new Uri("https://apiv2.bitcoinaverage.com/indices/global/ticker/short?crypto=BTC&fiat=USD");
CryptoAverage BTCAvg;
var request = new RestRequest();
response = Client.Execute(request);
BTCAvg = JsonConvert.DeserializeObject<CryptoAverage>(response.Content);
return Math.Round(BTCAvg.BTCUSD.Last, 2);
}
//async method
public async double GetBaselineAsync()
{
var Client = new RestClient();
IRestResponse response;
Client.BaseUrl = new Uri("https://apiv2.bitcoinaverage.com/indices/global/ticker/short?crypto=BTC&fiat=USD");
CryptoAverage BTCAvg;
var request = new RestRequest();
response = await Client.ExecuteAsync(request);
BTCAvg = JsonConvert.DeserializeObject<CryptoAverage>(response.Content);
return Math.Round(BTCAvg.BTCUSD.Last, 2);
}
There are two issues that I know of with the above code. The first line requires some some of Task keyword but I'm unsure how to code it. I've tried a number of things here without success.
Secondly, ExecuteAsync takes a 2nd argument but I'm unsure what. I've seen some examples of this, but they seem overly complicated for what I'm trying to do?
Appreciate any help you guys can offer!
If you want to use the Async Await pattern, you need to declare the method appropriately
public async Task<double> GetBaselineAsync()
{
var Client = new RestClient();
IRestResponse response;
Client.BaseUrl = new Uri("https://apiv2.bitcoinaverage.com/indices/global/ticker/short?crypto=BTC&fiat=USD");
CryptoAverage BTCAvg;
var request = new RestRequest();
response = await Client.ExecuteAsync(request);
BTCAvg = JsonConvert.DeserializeObject<CryptoAverage>(response.Content);
return Math.Round(BTCAvg.BTCUSD.Last, 2);
}
Usage
await GetBaselineAsync();
Yes.. You will have to let your async propagate through your code like a virus, or not use it at all.
Secondly, if ExecuteAsync is taking 2 seconds, its not because of .Net, there is not reason why the compiler would make your code pause for 2 seconds because of an await (even if you aren't using it correctly) Its the the call to the internet
If the library you use supports both sync and async methods(last usually with Async suffix) you should always use async ones. Async will create separate threads in your code in order to have better performance. And it will run concurrently when it needs. Async methods should almost in every case return Task or generic Task<>. If you want to call an asynchronous method in the synchronous method (in case of method signature doesn't allow you to use await keyword) you need to use .GetAwaiter().GetResult() upon a method which returns Task(in this case it will block the thread and won't run concurrently). Google around it worse it to spend time on it. Async await pattern was a huge step up of C# as language
EDIT: The solution was to change the declaration to;
public async Task<double> GetBaselineAsync()
And change ExecuteAsync to ExecuteTaskAsync. Full code;
public async Task<double> GetBaselineAsync()
{
var Client = new RestClient();
IRestResponse response;
Client.BaseUrl = new Uri("https://apiv2.bitcoinaverage.com/indices/global/ticker/short?crypto=BTC&fiat=USD");
CryptoAverage BTCAvg;
var request = new RestRequest();
response = await Client.ExecuteTaskAsync(request);
BTCAvg = JsonConvert.DeserializeObject<CryptoAverage>(response.Content);
return Math.Round(BTCAvg.BTCUSD.Last, 2);
}
Related
I'm trying to make a method that runs as an async method. The problem is the longest part is not 'awaitable' (not support the 'await' keyword ). I based my code using this link: here.
Some parts in my code have taken from Postman - HTTP POST to an API.
private async Task<byte[]> PostRequestToOptiRoutesAsync()
{
string urlCallBack = u.Trim(this.URLAchzraR4M);
var client = new RestClient(u.Trim(PrmtrimGlobliim_407_2.Mchrozt));
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("hfd_xml", u.Trim(BlovXMLBkshaOPT).Replace("\r", "").Replace("\n", "").Replace("\t", ""));
request.AddParameter("link", urlCallBack);
//UNTIL HERE - IT IS SYNC CODE AND NOT RELEVANT
//FROM HERE - THE POST TO THE API
IRestResponse response = client.Execute(request); // client.Execute is not awaitable - THE PROBLEMATIC ROW IS HERE
return u.UTF8FromAnsi(response.Content); // u.UTF8FromAnsi CONVERT THE RESULT- IGNORE IT
}
private async Task GetOptimalRoute()
{
Task<byte[]> result = PostRequestToOptiRoutesAsync();
await result;
}
The problem is that when I call GetOptimalRoute() using VS debug, my thread is not immediately moved to the next row, but it acts like sync code. It pauses for few seconds - unlike the code in the link above!!
How can I resolve this issue and make this code to be async?
Hello I dont get the difference between the following two asnyc functions, could someone explain it to me? Both of them doesnt return IRestResponse, so I cant access StatusCode field. Do I have to cast here?
public async Task<IRestResponse> Post<T>(string Ressource, T ObjTOPost) where T : new()
{
return await Task.Factory.StartNew(() =>
{
var client = new RestClient("test.com");
var request = new RestRequest(Ressource, Method.POST);
var response = client.Execute(request);
return response;
});
}
And this:
public async Task<IRestResponse> Post<T>(string Ressource, T ObjTOPost) where T : new()
{
var client = new RestClient("test.com");
var request = new RestRequest(Ressource, Method.POST);
var response = await client.ExecuteTaskAsync<T>(request);
return response;
}
Both of them doesnt return IRestResponse, so I cant access StatusCode field.
They return a Task<IRestResponse>. You can get the interface by awaiting the task, e.g.
var task = Post(resource, objectToPost);
IRestResponse response = await task;
Or in one line (more common):
var response = await Post(resource, objectToPost);
Difference between these two async functions
The second example is far more straightforward. The first example spins up an additional task and passes its awaitable back to the caller, whereas the second example awaits the RestClient directly. I see no reason to use the structure in the first example.
I was reading the following topic http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
and decided to write a common utility method in my library to do a GET on remote url via HTTPClient
public static async Task<T> GetAsync<T>(HttpGetObject getObject)
{
string baseUrl = getObject.BaseUrl;
string actionUrl = getObject.ActionRelativeUrl;
string acceptType = getObject.AcceptType;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseUrl);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(acceptType));
AddCustomHeadersToHttpClient(client, getObject);
// HTTP GET
HttpResponseMessage httpResponseMessage = await client.GetAsync(actionUrl).ConfigureAwait(false);
if (httpResponseMessage.IsSuccessStatusCode)
{
T response = await httpResponseMessage.Content.ReadAsAsync<T>().ConfigureAwait(false);
return response;
}
else
{
string message = httpResponseMessage.Content.ReadAsStringAsync().Result;
throw new Exception(message);
}
}
return default(T);
}
I know the "await httpResponseMessage.Content.ReadAsAsync().ConfigureAwait(false)" will prevent the deadlock in the above code
First:
My query is for "string message = httpResponseMessage.Content.ReadAsStringAsync().Result" line, will .Result can cause deadlock or not in that line?
Second:
If I call that code from UI like this:
public static object DoGet()
{
// Build getObject
var task = Utility.GetAsync(getObject);
task.Wait();
var response = task.Result;
return response;
}
Will that cause a deadlock?
Please note that I know to avoid all the mess with async-await, all the methods from UI to DAL must be async-await but I am not in position at this moment to change all that structure, my goal at this moment is to call HttpClient library and do a few GET operations.
So my questions is that will the above code can cause a deadlock?
Third:
Is task.Wait(); even needed in the above code?
In the general case, you should assume that yes, calling .Result or .Wait() on anything awaitable is dangerous and can deadlock (unless you are the library issuing the task, and you understand the full context). It is possible that it will work OK in some specific cases, but you should not rely on that behaviour, even if it works today.
Sorry for the name of my post but I am going to try to explain my problem.
I am building a client library to request an external API and I try to figure out how to make the methods of my library safe-threaded.
Basically the main class of my library looks like this :
public class MyCompanyApiClient
{
private readonly HttpClient _httpClient;
public MyCompanyApiClient(string baseUrl)
{
_httpClient = new HttpClient() {BaseAddress = new Uri(baseUrl)};
_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task<MyClassB> PostData(int id, MyClassA dataToPost)
{
var request = new HttpRequestMessage(HttpMethod.Post, $"objects/{id}");
request.Content = new StringContent(JsonConvert.SerializeObject(dataToPost), Encoding.UTF8,
"application/json");
var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
var stringContent = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<MyClassB>(stringContent);
}
public async Task<MyClassA > GetById(int id)
{
...
}
}
I'd like to ensure that any instance members of my client class are safe-threaded.
For the moment I plan to wrap the code inside each method into a Task.Run:
public async Task<MyClassB> PostData(int id, MyClassA dataToPost)
{
return await Task.Run(async () =>
{
var request = new HttpRequestMessage(HttpMethod.Post, $"objects/{id}");
request.Content = new StringContent(JsonConvert.SerializeObject(dataToPost), Encoding.UTF8,
"application/json");
var response = await _httpClient.SendAsync(request);
var stringContent = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<MyClassB>(stringContent);
});
}
By the way I don't even know if it is going to ensure this method to be safe-threaded.
Any help aprreciated ^^
Thread-safe doesn't mean multi-threading.
It means that some code is aware that it'll be used in multi-threaded cases, and they won't get corrupted, won't produce deadlocks and other threading-related issues.
Sometimes there's code that it's thread-safe per se, while sometimes you need to use thread-synchronization approaches like monitors, mutexes, reset events, semaphores and others, to protect critical code sections from being executed by one, two or n threads at once in order to avoid, again, deadlocks, corruptions and, basically, unexpected behaviors.
In your case, it seems like you consider thread-safe launching your PostDataas a thread in the thread pool. This is a bad choice, you don't need a new thread for this.
Could someone please help me modify the code below:
client.ExecuteAsync(request, response => {
Console.WriteLine(response.Content);
});
Basically I want to use ExecuteAsync method above but don't want to print but return response.Content to the caller.
Is there any easy way to achieve this?
I tried this but doesnt' work:
public T Execute<T>(RestRequest request) where T : new()
{
var client = new RestClient();
client.BaseUrl = BaseUrl;
client.Authenticator = new HttpBasicAuthenticator(_accountSid, _secretKey);
request.AddParameter("AccountSid", _accountSid, ParameterType.UrlSegment); // used on every request
var response = client.ExecuteAsync(request, response => {
return response.data);
});
}
The above code is from
https://github.com/restsharp/RestSharp
There's the thing... you can't return an asynchronously delivered value, because your calling method will already have returned. Blocking the caller until you have a result defeats the point of using ExecuteAsync. In this case, I'd return a Task<string> (assuming response.Content is a string):
Task<string> GetResponseContentAsync(...)
{
var tcs=new TaskCompletionSource<string>();
client.ExecuteAsync(request, response => {
tcs.SetResult(response.Content);
});
return tcs.Task;
}
Now, when the task completes, you have a value. As we move to c#5 async/await, you should get used to stating asynchrony in terms of Task<T> as it's pretty core.
http://msdn.microsoft.com/en-us/library/dd537609.aspx
http://msdn.microsoft.com/en-us/library/hh191443.aspx
With the help of #spender, this is what i got:
You can add new file in RestSharp project, and add this code:
public partial class RestClient
{
public Task<IRestResponse<T>> ExecuteAsync<T>(IRestRequest request)
{
var tcs=new TaskCompletionSource<IRestResponse<T>>();
this.ExecuteAsync(request, response =>
{
tcs.SetResult(
Deserialize<T>(request, response)
);
});
return tcs.Task;
}
}
This will practically return the full response, with status code and everything, so you can check if the status of the response is OK before getting the content, and you can get the content with:
response.Content
From reading the code it looks like you want to use ExecuteAsGet or ExecuteAsPost instead of the async implementation.
Or maybe just Execute- not sure exactly what type Client is.
At some point, there was a bunch of overloads introduced that support System.Threading.Tasks.Task and had the word "Task" in them. They can be awaited (like HttpClient's methods).
For instance:
ExecuteTaskAsync(request) (returns Task<IRestResponse>)
ExecuteGetTaskAsync(request) (returns Task<IRestResponse>)
ExecuteGetTaskAsync<T>(request) (returns Task<IRestResponse<T>>)
Those then became deprecated in later v106 versions in favour of Task-support being the default I believe, e.g. the first one became client.ExecuteAsync(request).
So these days you can just do:
var response = await client.ExecuteAsync(request);
return response.Content;