I have:
public static async Task<string> httpRequest(HttpWebRequest request)
I would like to do this:
string rez1;
static void test()
{
Task.Factory.StartNew(() => {
//How can I get result like rez1= httpRequest((HttpWebRequest)HttpWebRequest.Create("google.com")));
//or catch WebException here.
});
}
How can I do it?
Thanks
You have it mixed up a little bit. When your methods signature is:
public static async Task<string> httpRequest(HttpWebRequest request)
That means "this method is invoked asynchronously, i will call it and it will return imminently with a promise to finish in the future".
You should change your method to look like this:
Edit
Fixed the code according to the comments made.
public static Task<string> httpRequest(HttpWebRequest request)
{
return Task.Factory.Startnew(() = > {
return HttpWebRequest.Create("google.com")
}
}
When your method is marked as async, that means the caller might think it is "pure" async, which means no threads execute behind the scenes. If you do fire up a new thread (as you are doing here, by using a Thread Pool thread) you should explicitly comment your method and tell your invoker that he will be firing up a new thread.
You can save yourself firing up a new Task if you're using .NET 4.5 and have access to the new HttpClient class.
You can change your method to look like this:
public static async Task<string> httpRequest(HttpWebRequest request)
{
var httpClient = new HttpClient();
var response = await httpClient.GetAsync("http://www.google.com")
var stringResult = await response.Content.ReadAsStringAsync();
return stringResult;
}
Related
I was looking to make a settings method that executes the given settings and than execute the passed function/task. So instead of me typing a settings method each time
pubic void SomeMethod()
{
SettingsMethod()
//code
MainMethod()
}
public void SomeMethod2()
{
SettingsMethod()
/code...
MainMethod()
}
i wanted to do something like this:
public async static Task<T> ConfigureSettings<T>(Task<T> apiCallMethod, string localHost,int port, string riotToken)
{
client.BaseAddress = new Uri("https://"+localHost + ":"+port);
Console.WriteLine(client.BaseAddress);
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", riotToken);
return await apiCallMethod;
}
public async static Task<string> GetSummonerId()
{
HttpResponseMessage response = await client.GetAsync("/lol-login/v1/session");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
And be able to call it like this:
string summonerId = LeagueApiProcessor.ConfigureSettings(LeagueApiProcessor.GetSummonerId(), LeagueAccount.LocalHost, LeagueAccount.LocalHostPort, LeagueAccount.RiotToken).Result;
As i tried to debug the code, the
HttpResponseMessage response = await client.GetAsync("/lol-login/v1/session");
is executing much earlier than the
client.BaseAddress = new Uri("https://"+localHost + ":"+port);
Console.WriteLine(client.BaseAddress);
and that is making it crash each time.
I've tried changing the return types, but that just breaks my code even more. What would be the best approach to solve this, again this was my attempt to make a SettingsMethod() execute every time before the "MainMethod()" without having to type it in each function.
Rather than accept an already running Task<T>, accept a Func that will start the Task<T> and return it when you call it. This can be as simple as:
public async static Task<T> ConfigureSettings<T>(Func<Task<T>> apiCallMethod, string localHost,int port, string riotToken)
{
//...
return await apiCallMethod();
}
And:
LeagueApiProcessor.ConfigureSettings(LeagueApiProcessor.GetSummonerId, ...
Notice that we're not invoking GetSummonerId when creating the arguments to ConfigureSettings, we're instead implicitly converting it to a delegate that is called at the end of ConfigureSettings instead.
For more complex examples (say, when you need to pass arguments to the second method), you may need to pass a lambda instead:
LeagueApiProcessor.ConfigureSettings(() => CallSomeTaskReturningMethod(arg1,arg2), ...
I've got a class library for talking to a logging api server, the method "chain" is this:
Entry point ->
private static bool SendChecksumToServer(Checksum checksum)
{
var res = _api.GetAsync($"Checksum?assemblyName={checksum.CurrentAssembly}&checkSum={checksum.LogFileChecksum}&fileName={checksum.FileName}");
return _api.Deserialize<bool>(res.Result.Content.ReadAsStringAsync().Result);
}
Which calls this:
public async Task<HttpResponseMessage> GetAsync(string apiCall)
{
ApiGet get = new ApiGet();
return await get.GetAsync(apiCall, client);
}
Which calls this:
public async Task<HttpResponseMessage> GetAsync(string apiCall, HttpClient client)
{
var response = await client.GetAsync(apiCall);
return response;
}
This works completely fine when I use the class library within a console app, but as soon as I move it to an actual application (MVC) it stops working, it doesn't even hit the controller action at all, I've tried everything I can think of like checking firewalls, making sure the async is correct (although I'm sure it still isn't because the api not responding freezes the app, but I can't bubble the async any higher)
Most likely experiencing a deadlock because of .Result blocking call.
Don’t mix blocking and async code
Reference Async/Await - Best Practices in Asynchronous Programming
Refactor the code to be async all the way
private static async Task<bool> SendChecksumToServer(Checksum checksum) {
var res = await _api.GetAsync($"Checksum?assemblyName={checksum.CurrentAssembly}&checkSum={checksum.LogFileChecksum}&fileName={checksum.FileName}");
String data = await res.Result.Content.ReadAsStringAsync();
return _api.Deserialize<bool>(data);
}
Ensure what ever is calling SendChecksumToServer also awaits the task,
and also not using async-await in the other calls if nothing needs to be awaited.
public Task<HttpResponseMessage> GetAsync(string apiCall) {
ApiGet get = new ApiGet();
return get.GetAsync(apiCall, client);
}
ApiGet
public Task<HttpResponseMessage> GetAsync(string apiCall, HttpClient client) {
return client.GetAsync(apiCall);
}
I am working on an ASP.NET Core 2.2 application with Dapper. Virtually all methods follows the async/await pattern returning some sort of Task as a result.
Due to an issue we had with Dapper (I haven't personally investigated it, this part of the code I use as it is) but basically it boils down to the fact that if you want to execute in Transaction multiple async methods, which internally are calling other async methods and you may have several levels of nesting this way, you need to wrap all those method invocations within a single method which would be executed in a transaction.
The method that handles this is as follows:
public async Task<TOut> ExecuteInTransactionAsync<TOut>(
Delegate function,
params object[] parameters)
{
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
var result = await ((Task<TOut>)function.DynamicInvoke(parameters))
.ConfigureAwait(false);
scope.Complete();
return result;
}
}
So I have a very complex Entity which is saved by calling Save to a lot of smaller entities. This part of the code is working OK and looks like this:
public async SaveEntireEntity(EntityDTO entityDTO)
{
return await _transactionProvider.ExecuteInTransactionAsync<dynamic>(
new Func<object, Task<dynamic>>(async dto => await SaveInTransaction(dto)),
new { Name = entityDTO.Name, Address = entityDTO.Address, Age = entityDTO.Age });
}
And the SaveInTransaction method looks like:
private async Task<dynamic> SaveInTransaction(dynamic dto)
{
var entityId = await nameService.Add(dto.Name);
await addressService.Add(dto.Address);
await ageService.Add(dto.Age);
return entityId;
}
so this is simplified, but indeed I am calling a multiple services here, which on their part are calling multiple repositories and this works fine.
The Problem I have is when it comes to updating the same entity within a transaction. The whole purpose of showing the Save logic was to point out that at the end because I have this return entityId; I am able to chain everything together without any problems. However, as it is right now, by default our Update methods are not returning anything and this is where I can't figure out how to implement the Update logic.
Currently I have this:
public async Task UpdateEntireEntity(UpdateEntityDTO, entityDTO)
{
await _transactionProvider.ExecuteInTransactionAsync<dynamic>(
new Func<object, Task<dynamic>>(async dto => await UpdateInTransaction(dto)),
new { Name = entityDTO.Name, Address = entityDTO.Address, Age = entityDTO.Age });
}
And UpdateInTransaction looks like this:
private async Task<dynamic> UpdateInTransaction(dynamic dto)
{
await UpdateName(dto.Name);
await UpdateAddress(dto.Address);
await UpdateAge(dto.Age);
return await Task.FromResult<dynamic>(null);
}
This seems to work at least based on the several tests I made, however I really don't like this part:
return await Task.FromResult<dynamic>(null);
To me it seems like an ugly hack. The Update methods were thought not to return any value and this is just too artificial.
And even the worst part is that I can not figure out how implement the update method without having to return something.
One thing I've tried is to change the declaration of UpdateInTransaction to
private async Task UpdateInTransaction(dynamic dto)
and when I call the method I change it to:
await _transactionProvider.ExecuteInTransactionAsync<dynamic>(
new Func<object, Task>( async dto => await UpdateInTransaction(dto)..
But I got the following exception:
AsyncStateMachineBox1[System.Threading.Tasks.VoidTaskResult,
<fully-qualified- name>.<<UpdateEntireEntity>b__0>d] to type
'System.Threading.Tasks.Task1[System.Threading.Tasks.Task]'
.
So basically that's it. Sorry for the long post. I would really appreciate some well explained answer.
I would avoid the use of Delegate since it isn't typed:
public async Task<TOut> ExecuteInTransactionAsync<TOut>(Func<Task<TOut>> function)
{
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
var result = await (function()).ConfigureAwait(false);
scope.Complete();
return result;
}
}
This signature would mean you'd need to capture parameters rather than pass them:
public async Task<dynamic> SaveEntireEntity(EntityDTO entityDTO)
{
return await _transactionProvider.ExecuteInTransactionAsync(
async () => await SaveInTransaction(
new { Name = entityDTO.Name, Address = entityDTO.Address, Age = entityDTO.Age }));
}
Once you're using the strongly-typed Func<Task<T>> instead of Delegate in your method signature, you can create an overload for ExecuteInTransactionAsync as such:
public async Task ExecuteInTransactionAsync(Func<Task> function)
{
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
await (function()).ConfigureAwait(false);
scope.Complete();
}
}
which can be used as such:
public async Task UpdateEntireEntity(UpdateEntityDTO entityDTO)
{
await _transactionProvider.ExecuteInTransactionAsync(
async () => await UpdateInTransaction(
new { Name = entityDTO.Name, Address = entityDTO.Address, Age = entityDTO.Age }));
}
private async Task UpdateInTransaction(dynamic dto)
{
await UpdateName(dto.Name);
await UpdateAddress(dto.Address);
await UpdateAge(dto.Age);
}
You can change
private async Task<dynamic> UpdateInTransaction(dynamic dto)
{
await UpdateName(dto.Name);
await UpdateAddress(dto.Address);
await UpdateAge(dto.Age);
return await Task.FromResult<dynamic>(null);
}
to
private async Task<dynamic> UpdateInTransaction(dynamic dto)
{
await UpdateName(dto.Name);
await UpdateAddress(dto.Address);
await UpdateAge(dto.Age);
return null;
}
Consider the following method:
private async Task<Task<Response>> SendAsync(string data)
{
this.Tcs = new TaskCompletionSource<Response>();
await this.Stream.WriteAsync(...);
await this.Stream.FlushAsync();
return this.Tcs.Task;
}
I have an async method, which I expect to return Task<Response>. But since I want to return TaskCompletionSource<Response> (which gets set elsewhere, so I can't await it here), I have to actually return Task<Task<Response>> instead.
In the calling code, I have two ways of dealing with it while hiding this ugliness from the outside of the class. Assuming the response is not important and can be ignored, I can simply return a Task:
public Task GetAsync(string key)
{
return this.SendAsync("GET " + key);
}
On the other hand, if I want the response, I have to use this ugly await await to make it work:
public async Task<Response> GetAsync(string key)
{
return await await this.SendAsync("GET " + key);
}
Is there a better way of dealing with this, i.e. returning the Task<Response> from SendAsync() without exposing a Task<Task<Response>> outside the class, and at the same time not using the await await?
I'm not sure why you need to use a TaskCompletionSource inside an async method. Usually you either do the one or the other.
But if you must then forget returning the TaskCompletionSource.Task. Simply await the task like you do the rest of the async methods (WriteAsync and FlushAsync) and change the method to return Task<Response>:
private async Task<Response> SendAsync(string data)
{
this.Tcs = new TaskCompletionSource<Response>();
await this.Stream.WriteAsync(...);
await this.Stream.FlushAsync();
return await this.Tcs.Task;
}
That way the async method returns a task that gets completed when there's a Response so you only need to await SendAsync("...") once.
The answer by #i3arnon is a good solution, however another solution is to use the Unwrap extension method.
The TaskExtensions.Unwrap method is designed for converting a Task<Task<TResult>> into a Task<TResult> and can be used as follows:
public Task<Response> GetAsync(string key)
{
return this.SendAsync("GET " + key).Unwrap();
}
Any result, exception or cancellation will be propagated correctly to the resulting Task<TResult>.
I've made a nice controller helper in my MVC project that allows me to return similarly structured result payloads when I make any ajax request. It looks like this:
public static JsonNetResult Responsify<T>(Func<T> func)
{
AjaxResponse response;
var result = new JsonNetResult
{
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
try
{
var resp = func();
response = AjaxResponse.SuccessResponse(resp);
result.Data = response;
}
catch (Exception e)
{
response = AjaxResponse.ErrorResponse(e.Message);
result.Data = response;
}
return result;
}
and it gets used like this:
[HttpPost]
public JsonNetResult Link(LinkInstruction instruction)
{
return ControllerHelper.Responsify(() => _linkHandler.Link(instruction));
}
where _linkHandler.Link is not async.
My issue is I have some async handlers that I would like to invoke using this pattern and I can't figure out how to await the function. I've tried Task.Factory.StartNew as well as wrapping the lambda in async/await and I can't quite figure it out.
Create a version of Responsify - call it ResponsifyAsync - that specifies that the passed Func must return a Task<T> (therefore meaning you can await it):
public async static JsonNetResult ResponsifyAsync<T>(Func<Task<T>> func)
{
...
}
This would do much what your current function does, but would await func() instead of just executing it.
You must then pass a Func delegate that returns a Task to this method. When calling an async library in the delegate, since the async method you're calling already returns a Task, this will simply take the form:
var x = await ResponsifyAsync(() => _someClass.MyMethodAsync(someParameter));
Or, if the method is parameterless...
var x = await ResponsifyAsync(_someclass.MyMethodAsync);
I'll let you flesh out the method but this format should set you off on the right lines.