I have a client server app. Wpf - Web api I am having a bit of troubles as this is working on one machine but when I switch to another machine it doesn't.
public async Task<IEnumerable<T>> Get()
{
var result = (IEnumerable<T>)null;
//Gets to this line and does not throw exception
var response = await _httpClient.GetAsync(BaseApiAddress);
if (!response.IsSuccessStatusCode)
{
ThrowInvalidException(response);
}
var resultAsString = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<IEnumerable<T>>(resultAsString);
return result;
}
API method:
[HttpGet]
public virtual IEnumerable<T> Get()
{
var items = Repository.Get().ToArray();
return items;
}
and Repository:
public IQueryable<T> Get()
{
return _context.Set<T>();
}
I get to the api and it gets the data while debugging through the code it has the data and looks as if there it completes the method on the api. all of that said it never returns to the GetAsync method.
I have hit a brick wall here and really don't even know where to start looking from here. Any Suggestions would be very helpful.
If you run under a synchronization context, you'll get a deadlock if:
The caller waits synchronously on a task (for example, calling task.Result
Inside of the task, you use await
The fix is to use .ConfigureAwait(false) to avoid posting the continuation on the synchronization context:
var response = await _httpClient.GetAsync(BaseApiAddress).ConfigureAwait(false);
Of course, as much as possible, you should avoid waiting synchronously on a task.
Related
In my .Net 6 WebPI service, I am queueing work to a background task queue, very closely based on the example here, but I could post parts of my implementation if that would help:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-6.0&tabs=visual-studio#queued-background-tasks
I am running into unexpected behavior where control is not returned to the caller, even after the return Ok(..) completes in the controller. Instead the request only completes after the await Task.Delay(1000); line is reached on the queued work item. The request returns to the client as soon as this line is reached, and does not need to wait for the Delay to finish.
I'm guessing this is because of the await either starting a new async context, or someone un-sticking the async context of the original request. My intention is for the request to complete immediately after queuing the work item.
Any insight into what is happening here would be greatly appreciated.
Controller:
public async Task<ActionResult> Test()
{
var resultMessage = await _testQueue.DoIt();
return Ok(new { Message = resultMessage });
}
Queueing Work:
public TestAdapter(ITaskQueue taskQueue)
{
_taskQueue = taskQueue;
}
public async Task<string> DoIt()
{
await _taskQueue.QueueBackgroundWorkItemAsync(async (_cancellationToken) =>
{
await Task.Delay(1000);
var y = 12;
});
return "cool";
}
IoC:
services.AddHostedService<QueueHostedService>();
services.AddSingleton<ITTaskQueue>(ctx =>
{
return new TaskQueue(MaxQueueCount);
});
TaskQueue:
private readonly Channel<BackgroundTaskContext> _queue;
public TaskQueue(int capacity)
{
var options = new BoundedChannelOptions(capacity)
{
FullMode = BoundedChannelFullMode.Wait
};
_queue = Channel.CreateBounded<BackgroundTaskContext>(options);
}
public async ValueTask QueueBackgroundWorkItemAsync(
Func<CancellationToken, ValueTask> workItem)
{
if (workItem == null)
{
throw new ArgumentNullException(nameof(workItem));
}
await _queue.Writer.WriteAsync(new BackgroundTaskContext(workItem, ...));
}
Not sure what you expect here. I'm assuming you want the async method to return the cool in the api response. That's fine but because your also awaiting the async call with in DoIt(), then it pauses until QueueBackgroundWorkItemAsync finishes. You could remove the await and it will run and return as you expect.
I can't say that I'm a big fan of that design as you lose contact with it with exception of the cancellation token. Another thought would be to Send that work off to a console job or function app using message bus or even another http call.
Additional Notes:
Async can be complicated to explain because in reality, it wraps up code and executes on a thread of it's choosing. The await simulates the synchronous behavior.
await Task.Delay(1000); // Runs on it's own thread but still halts code execution for 1 second.
await _taskQueue.QueueBackgroundWorkItemAsync(async (_cancellationToken) // Waits for control to be returned from the code inside.
var resultMessage = await _testQueue.DoIt(); // Always waits for the code inside to complete.
If your wanting something to run without pausing code execution, you can either remove the await or add a Task.Run(() => { }); pattern. Is it a good idea is a whole other question. It also matters whether you need information back from the async method. If you don't await it then you'll get null back as it doesn't wait around for the answer to be computed.
This appears just to have been user error using the debugger. The debugger is switching to the background task thread and hitting breakpoints there before the response fully returns giving the appearance that control was not being returned to the client and being carried into the background task.
Even after adding some synchronous steps in QueueBackgroundWorkItemAsync and putting breakpoints on them, control was not immediately returned to the original http call. Only after I tried adding a long running task like await Task.Delay(1000); did enough time/ticks pass for the http response to return. I had conflated this with just the await somehow freeing up the original http context.
The following code gets a list of investments belonging to a customer from 3 different resources. The flow starts with a controller's call and follows the flow described below where all methods are declared as async and called with await operator.
I'm wondering if is there a problem making all methods as async. Is there any performance penalty? Is it a code smell or an anti-pattern?
I know there are things that must be waited like access url, get data from cahce, etc. But I think there are things like filling a list or sum some few values doesn't need to be async.
Below follow the code (some parts where ommited for clearness):
Controller
{HttpGet]
public async Task<IActionResult> Get()
{
Client client = await _mediator.Send(new RecuperarInvestimentosQuery());
return Ok(cliente);
}
QueryHandler
public async Task<Client> Handle(RecoverInvestimentsQuery request, CancellationToken cancellationToken)
{
Client client;
List<Investiment> list = await _investimentBuilder.GetInvestiments();
client = new Cliente(request.Id, list);
return client;
}
InvestmentBuilder
public async Task<List<Investiment>> GetInvestiments()
{
ListInvestiments builder = new ListInvestiments();
await builder.BuildLists(_builder);
// here I get the List<Investiment> list already fulfilled to return to the controller
return list;
}
BuildLists
public async Task BuildLists(IBuilder builder)
{
Task[] tasks = new Task[] {
builder.GetFundsAsync(), //****
builder.ObterTesouro(),
builder.ObterRendaFixa()
};
await Task.WhenAll(tasks);
}
Funds, Bonds and Fixed Income Services (***all 3 methods are equal, only its name vary, so I just put one of them for the sake of saving space)
public async Task GetFundsAsync()
{
var listOfFunds = await _FundsService.RecoverFundsAsync();
// listOfFunds will get all items from all types of investments
}
Recover Funds, Bonds and Fixed Incomes methods are equals too, again I just put one of them
public async Task<List<Funds>> RecoverFundsAsync()
{
var returnCache = await _clientCache.GetValueAsync("fundsService");
// if not in cache, so go get from url
if (returnCache == null)
{
string url = _configuration.GetValue<string>("Urls:Funds");
var response = await _clienteHttp.ObterDadosAsync(url);
if (response != null)
{
string funds = JObject.Parse(response).SelectToken("funds").ToString();
await _clienteCache.SetValueAsync("fundService", funds);
return JsonConvert.DeserializeObject<List<Funds>>(fundos);
}
else
return null;
}
return JsonConvert.DeserializeObject<List<Funds>>(returnCache);
}
HTTP Client
public async Task<string> GetDataAsync(string Url)
{
using (HttpClient client = _clientFactory.CreateClient())
{
var response = await client.GetAsync(Url);
if (response.IsSuccessStatusCode)
return await response.Content.ReadAsStringAsync();
else
return null;
}
}
Cache Client
public async Task<string> GetValueAsync(string key)
{
IDatabase cache = Connection.GetDatabase();
RedisValue value = await cache.StringGetAsync(key);
if (value.HasValue)
return value.ToString();
else
return null;
}
Could someone give a thought about that?
Thanks in advance.
Your code looks okay for me. You are using async and await just for I/O and web access operations, and it perfectly fits for async and await purposes:
For I/O-bound code, you await an operation that returns a Task or Task inside of an async method.
For CPU-bound code, you await an operation that is started on a background thread with the Task.Run method.
Once you've used async and await, then all pieces of your code tends to become asynchronous too. This fact is described greatly in the MSDN article - Async/Await - Best Practices in Asynchronous Programming:
Asynchronous code reminds me of the story of a fellow who mentioned
that the world was suspended in space and was immediately challenged
by an elderly lady claiming that the world rested on the back of a
giant turtle. When the man enquired what the turtle was standing on,
the lady replied, “You’re very clever, young man, but it’s turtles all
the way down!” As you convert synchronous code to asynchronous code,
you’ll find that it works best if asynchronous code calls and is
called by other asynchronous code—all the way down (or “up,” if you
prefer). Others have also noticed the spreading behavior of
asynchronous programming and have called it “contagious” or compared
it to a zombie virus. Whether turtles or zombies, it’s definitely true
that asynchronous code tends to drive surrounding code to also be
asynchronous. This behavior is inherent in all types of asynchronous
programming, not just the new async/await keywords.
Imagine this is a method performing a DB query and returning a result, which in case of null is replaced with a default value (Null object pattern).
public ResultObj Get()
{
var result = dbContext.GetSomeResult();
return result ?? ResultObj.NullValue;
}
Imagine this DB query is a long-running process, so I would use async/await to execute this process in a separate thread. Suppose that the dbContext.GetSomeResultAsync() method is available.
How can be this method converted in an asynchronous one so that I can write something like this?
var resultTask = GetAsync();
var otherResultTask = GetSomethingElseAsync();
Task.WaitAll(resultTask, otherResultTask);
var myResult = resultTask.Result;
var myOtherResult = otherResultTask.Result;
I tried this solution.
public async Task<ResultObj> GetAsync()
{
var result = await dbContext.GetSomeResultAsync();
return result ?? ResultObj.NullValue;
}
First, I'm wondering why this code compiles: why can I return ResultObj when Task<ResultObj> is expected?
Second, this code predictably results in a deadlock, as clearly explained by the great number of resources about async deadlocks anti-patterns. The deadlock can be prevented by using .ConfigureAwait(false) method after the async call. Is this the right way to go? Are there any hidden drawbacks in this case? Is it a general rule?
I also tried this.
public async Task<ResultObj> GetAsync()
{
return await Task.Run(() => {
var result = dbContext.GetSomeResult();
return result ?? ResultObj.NullValue;
});
}
This results in a deadlock, too. This time I cannot even figure out why.
Edit: possible solution
Finally, after having read this, I found a solution to my problem.
My generic query wrapper method is like this.
public async Task<ResultObj> GetAsync()
{
var result = await dbContext.GetSomeResultAsync();
return result ?? ResultObj.NullValue;
}
On calling method, I use this pattern.
public async Task<CollectedResults> CollectAsync()
{
var resultTask = GetAsync();
var otherResultTask = GetSomethingElseAsync();
//here both queries are being executed.
//...in the while, optionally, here some other synchronous actions
//then, await results
var result = await resultTask;
var otherResult = await otherResultTask;
//here process collected results and return
return new CollectedResults(...);
}
It is worth mentioning that the above code, wrapped in a domain class, is called by a Controller action. In order for this to work I had to make async the methods all the way up, until Controller action, which now appears as follows.
public async Task<CollectedResults> Get()
{
return await resultsCollector.CollectAsync();
}
This way, deadlock doesn't happen anymore and execution time greatly improves with respect to the synchronous version.
I don't know if this is the canonical way of executing parallel queries. But it works and I don't see particular pitfalls in the code.
First of all, regarding :
so I would use async/await to execute this process in a separate thread.
There is no new thread created when we use async and await
Secondly:
why can I return ResultObj when Task is expected?
the Task<TResult> as return type of method tells that it returns a Task of type TResult but we need to return object of type that TResult back from it so the method can be awaited and when using Task<TResult> as reutrn type we should be using async and await to do the work.
Lastly:
this code predictably results in a deadlock
You are using async keyword with method signatures and also await the next async method call being done from within the method. So apparently it looks like the code in first example you have posted shouldn't be deadlocked, if the method GetSomeResultAsync you are consuming is really a async method and is properly implemented.
I suggest to study more about the async await before getting in to it, following is a good article to start with:
https://blog.stephencleary.com/2012/02/async-and-await.html
I'm trying to figure out if using aysnc/await will help application throughput when using HttpClient to POST to an external api.
Scenario: I have a class that POST's data to a payment processors web api. There are 4 steps to POST a payment:
1 - POST Contact
2 - POST Transaction
3 - POST Donation
4 - POST Credit Card Payment
Steps 1 - 4 must be sequential in order specified above.
My application does not have any "busy work" to do when waiting for a response from the payment processor - in this scenario does using async/await for the operations below make sense? Will it increase application throughput during high volume? Thanks!
Edit: (question was marked as not clear)
1. My application is a web api (microservice)
2. I'm using .Result (blocking) to avoid async/await (clearly this is wrong!)
3. We will have "spike" loads of 1000 req/minute
public virtual ConstituentResponse PostConstituent(Constituent constituent)
{
var response = PostToUrl<Constituent>("/api/Constituents", constituent);
if (!response.IsSuccessStatusCode)
HandleError(response);
return response.Content.ReadAsAsync<ConstituentResponse>().Result;
}
public virtual TransactionResponse PostTransaction(Transaction transaction)
{
var response = PostToUrl<Transaction>("/api/Transactions", transaction);
if (!response.IsSuccessStatusCode)
HandleError(response);
return response.Content.ReadAsAsync<TransactionResponse>().Result;
}
public virtual DonationResponse PostDonation(Donation donation)
{
var response = PostToUrl<Donation>("/api/Donations", donation);
if (!response.IsSuccessStatusCode)
HandleError(response);
return response.Content.ReadAsAsync<DonationResponse>().Result;
}
public virtual CreditCardPaymentResponse PostCreditCardPayment(CreditCardPayment creditCardPayment)
{
var response = PostToUrl<CreditCardPayment>("/api/CreditCardPayments", creditCardPayment);
if (!response.IsSuccessStatusCode)
HandleError(response);
return response.Content.ReadAsAsync<CreditCardPaymentResponse>().Result;
}
protected virtual HttpResponseMessage PostToUrl<T>(string methodUri, T value)
{
return _httpClient.PostAsJsonAsync(methodUri, value).Result;
}
The five methods above are called from another class/function:
public virtual IPaymentResult Purchase(IDonationEntity donation, ICreditCard creditCard)
{
var constituentResponse = PostConstituent(donation);
var transactionResponse = PostTransaction(donation, constituentResponse);
var donationResponse = PostDonation(donation, constituentResponse, transactionResponse);
var creditCardPaymentResponse = PostCreditCardPayment(donation, creditCard, transactionResponse);
var paymentResult = new PaymentResult
{
Success = (creditCardPaymentResponse.Status == Constants.PaymentResult.Succeeded),
ExternalPaymentID = creditCardPaymentResponse.PaymentID,
ErrorMessage = creditCardPaymentResponse.ErrorMessage
};
return paymentResult;
}
You cannot actually utilize await Task.WhenAll here as when you are purchasing the next asynchronous operation relies on the result from the previous. As such you need to have them execute in the serialized manner. However, it is still highly recommended that you use async / await for I/O such as this, i.e.; web service calls.
The code is written with the consumption of Async* method calls, but instead of actually using the pattern -- it is blocking and could be a potential for deadlocks as well as undesired performance implications. you should only ever use .Result (and .Wait()) in console applications. Ideally, you should be using async / await. Here is the proper way to adjust the code.
public virtual async Task<ConstituentResponse> PostConstituenAsync(Constituent constituent)
{
var response = await PostToUrlAsync<Constituent>("/api/Constituents", constituent);
if (!response.IsSuccessStatusCode)
HandleError(response);
return await response.Content.ReadAsAsync<ConstituentResponse>();
}
public virtual async Task<TransactionResponse PostTransactionAsync(Transaction transaction)
{
var response = await PostToUrl<Transaction>("/api/Transactions", transaction);
if (!response.IsSuccessStatusCode)
HandleError(response);
return await response.Content.ReadAsAsync<TransactionResponse>();
}
public virtual async Task<DonationResponse> PostDonationAsync(Donation donation)
{
var response = await PostToUrl<Donation>("/api/Donations", donation);
if (!response.IsSuccessStatusCode)
HandleError(response);
return await response.Content.ReadAsAsync<DonationResponse>();
}
public virtual async Task<CreditCardPaymentResponse> PostCreditCardPaymentAsync(CreditCardPayment creditCardPayment)
{
var response = await PostToUrlAsync<CreditCardPayment>("/api/CreditCardPayments", creditCardPayment);
if (!response.IsSuccessStatusCode)
HandleError(response);
return await response.Content.ReadAsAsync<CreditCardPaymentResponse>();
}
protected virtual Task<HttpResponseMessage> PostToUrlAsync<T>(string methodUri, T value)
{
return _httpClient.PostAsJsonAsync(methodUri, value);
}
Usage
public virtual await Task<IPaymentResult> PurchaseAsync(IDonationEntity donation, ICreditCard creditCard)
{
var constituentResponse = await PostConstituentAsync(donation);
var transactionResponse = await PostTransactionAsync(donation, constituentResponse);
var donationResponse = await PostDonationAsync(donation, constituentResponse, transactionResponse);
var creditCardPaymentResponse = await PostCreditCardPaymentAsync(donation, creditCard, transactionResponse);
var paymentResult = new PaymentResult
{
Success = (creditCardPaymentResponse.Status == Constants.PaymentResult.Succeeded),
ExternalPaymentID = creditCardPaymentResponse.PaymentID,
ErrorMessage = creditCardPaymentResponse.ErrorMessage
};
return paymentResult;
}
First of all the way the code is written now does not help at all because you are blocking all the time by calling Result. If this was a good thing to do, why wouldn't all APIs simply do this internally for you?! You can't cheat with async...
You will only see throughput gains if you exceed the capabilities of the thread pool which happens in the 100s of threads range.
he average number of threads needed is requestsPerSecond * requestDurationInSeconds. Plug in some numbers to see whether this is realistic for you.
I'll link you my standard posts on whether to go sync or async because I feel you don't have absolute clarity for when async IO is appropriate.
https://stackoverflow.com/a/25087273/122718 Why does the EF 6 tutorial use asychronous calls?
https://stackoverflow.com/a/12796711/122718 Should we switch to use async I/O by default?
Generally, it is appropriate when the wait times are long and there are many parallel requests running.
My application does not have any "busy work" to do when waiting for a response
The other requests coming in are such busy work.
Note, that when a thread is blocked the CPU is not blocked as well. Another thread can run.
When you are doing async/await, you should async all the day.
Read Async/Await - Best Practices in Asynchronous Programming
You need to make them return async
public virtual async Task ConstituentResponse PostConstituent(Constituent constituent)
{
var response = PostToUrl<Constituent>("/api/Constituents", constituent);
if (!response.IsSuccessStatusCode)
HandleError(response);
return await response.Content.ReadAsAsync<ConstituentResponse>();
}
//...
//etc
And then from the main function
await Task.WhenAll(constituentResponse, transactionResponse, donationResponse, creditCardPaymentResponse);
Edit: Misread OP. Don't use await Task.WhenAll for synchronous calls
I'm using .NET 4.0, so I can't use the async/await keywords.
After I laboriously set up tasks and continuations instead of just calling .Result, all I got for my efforts was a mess and it runs 46% slower on a workload of a few dozen HTTP GETs. (I get similar perf degradation if I call the workload in serial or in a Parallel loop)
What must I do to see any performance benefit?
//Slower code
public UserProfileViewModel GetAsync(Guid id)
{
UserProfileViewModel obj = null;//Closure
Task result = client.GetAsync(id.ToString()).ContinueWith(responseMessage =>
{
Task<string> stringTask = responseMessage.Result
.Content.ReadAsStringAsync();
Task continuation = stringTask.ContinueWith(responseBody =>
{
obj = JsonConvert
.DeserializeObject<UserProfileViewModel>(responseBody.Result);
});
//This is a child task, must wait before returning to parent.
continuation.Wait();
});
result.Wait();
return obj;
}
//Faster code
public UserProfileViewModel GetSynchr(Guid id)
{
//Asych? What's is that?
HttpResponseMessage response = client.GetAsync(id.ToString()).Result;
string responseBody = response.Content.ReadAsStringAsync().Result;
return JsonConvert.DeserializeObject<UserProfileViewModel>(responseBody);
}
You are using "async" methods but doing everything synchronously. That certainly won't be any better than doing everything synchronously with the synchronous methods.
Take a look at this:
public Task<UserProfileViewModel> GetAsync(Guid id)
{
var uri = id.ToString();
return client.GetAsync(uri).ContinueWith(responseTask =>
{
var response = responseTask.Result;
return response.Content.ReadAsStringAsync().ContinueWith(jsonTask =>
{
var json = jsonTask.Result;
return JsonConvert.DeserializeObject<UserProfileViewModel>(json);
});
}).Unwrap();
}
Notice how the method returns a Task and the continuations are returned from the method. This allows your method to return almost instantly, giving the caller a handle to the running work and whatever continuations need to happen. The returned task will only be complete once everything is done, and it's result will be your UserProfileViewModel.
The Unwrap method takes a Task<Task<UserProfileViewModel>> and turns it into a Task<UserProfileViewModel>.