In this method:
private async List<stuff> GetData()
{
return await _appCache.GetAsync("SiteStructurePages",
() => _repository.GetSomeStuff());
}
is there any reason to keep it async? My code will execute in async manner just once, and all subsequent requests will use cache. Async spreads up to other parts of my application, that doesn't hit database, because lots of stuff is cached.
Edit:
My application is IIS website application.
is there any reason to keep it async?
That really depends on you. If you actually need to take advantage of asynchronous operations, which is being able to scale, then do keep it. Otherwise, if you don't, use a synchronous API. it's all up to you and what you actually make use of in your code base.
I understand the fact that you're worried about async methods going "all the way" and actually altering your entire code-base to become async. That's why you should do it as long as it's worth it.
Side note - you can slightly modify your code to save yourself the async state-machine generation:
private Task<List<stuff>> GetData()
{
return _appCache.GetAsync("SiteStructurePages",
() => _repository.GetSomeStuff());
}
If you can ensure that the call is quick and that it's not going to block a UI thread, then sure, you don't need Async on this one.
However, if such things are not in your control, then I would leave it asynchronous.
Related
I have an existing code block with Linq to SQL queries and HTTP requests, that I'd like to make async for the purpose of using less threads.
Will it suffice to put the code block in an async method, like so?
public async Task<Customer> ProcessACustomer()
{
return await GetCustomer();
}
public Task<Customer> GetCustomer()
{
// Linq to SQL query here
// HTTP request here
Customer customer;
return Task.FromResult<Customer>(customer);
}
...or do I have to make every piece of logic in GetCustomer() async to accomplish this?
My hurdle here is that I have a ton of logic in that method (oversimplified above), so time will be an issue. Also, I can't seem to convert my Linq To SQL queries to async, as the async extension methods are not available for some reason (System.Data.Linq.Table does not contain a definition for FirstOrDefaultAsync() f.ex.).
Will it suffice to put the code block in an async method, like so?
No. The GetCustomer method is not asynchronous. It synchronously performs its work and then returns a completed task. This will not save any threads.
do I have to make every piece of logic in GetCustomer() async to accomplish this?
If you want to convert to async, then you should start at the opposite end. Don't start with the goal of making ProcessACustomer (or GetCustomer) asynchronous. Instead, start with the lowest-level API. Whatever your db access method is, make that asynchronous first and then let the async grow out from there.
My hurdle here is that I have a ton of logic in that method (oversimplified above), so time will be an issue.
This is a classic tradeoff. It may be worthwhile to convert to async, or it may be worthwhile to buy a few more servers instead.
I have a Web API controller (ASP.NET Core 5). Some of my APIs are asynchronous and some of them not. My question is next: Is there any advantages of using public **Task<T>** WebApiMethod + Task.FromResult() in Web API controllers if my method is synchronous?
For example:
public Task<string> GetSomeData()
{
// some synchronous processing...
return Task.FromResult(result);
}
Should I turn the example code above to something like this?
public string GetSomeData()
{
// some synchronous processing...
return result;
}
If the api is doing synchronous work it should have a synchronous signature. it will make the readability and understanding of the function clearer to other developers and will prevent misunderstanding when reading this function again in the future.
In the future, if the method will need to be modified to have an asynchronous task to do, you can change the signature to have an asynchronous signature.
You should use synchronous methods if the work is synchronous.
Yet, you should use Task signatures if you use some form of caching (e.g. with the proxy pattern). Then, of course if you already did the expensive I/O work, use Task.FromResult to return the cached result, and return the I/O task if it has to be newly downloaded.
It shouldn't have much difference in the way it is executed. If you can make the processing part asynchronous then it would make some difference.
I'm in a situation where we have some code that is run by user input (button click), that runs through a series of function calls and result in generating some data (which is a quite heavy operation, several minutes). We'd like to use Async for this so that it doesn't lock up the UI while we're doing this operation.
But at the same time we also have a requirement that the functions will also be available through an API which preferably should be synchronous.
Visualization/Example (pseudo-code):
public async void Button_Click() // from UI context
{
await instanceOfClassA.FuncA();
// some code
}
public async Task ClassA.FuncA()
{
await instanceOfClassB.FuncB()
// some code
}
public async Task ClassB.FuncB()
{
await instanceOfClassC.SomeHeavyFunc()
// some code
}
public async Task ClassC.SomeHeavyFunc()
{
// some heavy calculations
}
// Also need to provide a public synchronous API function
public void SomeClass.SynchronousAPIFunc()
{
// need to call differentInstanceOfClassB.FuncB()
}
Is there a way to make it so that the public API function does the waiting for the async operation internally?
EDIT:
In this post, user Rachel provides two answers to the question. Both seem interesting, though I'm unsure which one would offer the least amount of risk/side effects.
EDIT2:
I should note that we're using .NET v4.6.1.
Thanks in advance.
The problem with making "synchronous" versions of your methods that just call the asynchronous versions is that it can cause deadlocks, especially if the person calling this code is not aware that this is what is happening.
If you really want to make synchronous versions, then follow Microsoft's lead and write completely new methods that do not use any asynchronous code. For example, the implementation for File.ReadAllLines() doesn't use any of the same code as File.ReadAllLinesAsync().
If you don't want to do that, then just don't provide synchronous versions of your methods. Let the caller make the decision on how to deal with it. If they want to block synchronously on it, then they can mitigate the risk of deadlock.
But at the same time we also have a requirement that the functions will also be available through an API which preferably should be synchronous.
If you have the need to expose both a synchronous and asynchronous API, I recommend the boolean argument hack. This looks like:
public Task<T> FuncBAsync() => FuncBAsync(sync: false);
public T FuncB() => FuncBAsync(sync: true).GetAwaiter().GetResult();
public async Task<T> FuncBAsync(bool sync)
{
// Note: is `sync` is `true`, this method ***must*** return a completed task.
...
}
Is there a way to make it so that the public API function does the waiting for the async operation internally?
I do not recommend using direct blocking (e.g., GetAwaiter().GetResult()), as the straightforward implementation will lead to deadlocks.
EDIT: In this post, user Rachel provides two answers to the question.
I strongly recommend against using that solution. It uses a nested message loop with a custom SynchronizationContext, but doesn't do COM pumping. This can cause problems particularly if called from a UI thread. Even if the pumping isn't a problem, this solution can cause unexpected re-entrancy, which is a source of countless, extremely subtle, and difficult-to-find bugs.
You can utilize .GetAwaiter().GetResult()
as per your example, it would look like:
public void SomeClass.SynchronousAPIFunc()
{
// need to call differentInstanceOfClassB.FuncB()
ClassB.FuncB().GetAwaiter().GetResult();
}
Also, a good reference on when to not use the above can be found at Dont Block on Async Code
We're in the process of refactoring all, or a large portion of our .NET 4.6 MVC WebAPI controller methods to async methods.
This seems like it will work well for methods that have a lower level invocation of a method that is awaitable such as SQL command execution; however we are utilizing an in-memory distributed caching framework by Alachisoft called NCache (4.6 SP2 to be exact), which does not offer any truly asynchronous methods.
Would it be worth creating an async helper method that would expose a awaitable Task<object> return type?
Traditionally using the NCache API, you Get an object from cache by a Key in the following usage;
NCacheObject.Get(string);
The proposal is to create a helper method of the following;
protected static async Task<Object> GetAsync(string key, Cache nCache)
{
Task<Object> getTask = new Task<Object>(() => nCache.Get(key));
getTask.Start();
return await getTask.ConfigureAwait(false);
}
So that it would then allow full waterfall of async methods up to the entry controller method as such;
public static async Task<Tuple<List<SomeModel>, bool, string>> GetSomeModelList(string apiKey)
{
return newTuple<List<SomeModel>, bool, string>(await GetAsync("GetSomeModelKey", CacheInstance).ConfigureAwait(false), true, "Success message");
}
And finally the controller method;
[HttpGet, Route("Route/Method")]
public async Task<ResponseOutputModel<List<SomeModel>>> GetSomeModelList()
{
ResponseOutputModel<List<SomeModel>> resp = new ResponseOutputModel<List<SomeModel>>();
try
{
Tuple<List<SomeModel>, Boolean, String> asyncResp = await CacheProcessing.GetSomeModelList(GetApiKey()).ConfigureAwait(false);
resp.Response = asyncResp.Item1;
resp.Success = asyncResp.Item2;
resp.Message = asyncResp.Item3;
}
catch (Exception ex)
{
LoggingHelper.Write(ex);
resp.StatusCode = Enumerations.ApiResponseStatusCodes.ProcessingError;
resp.Success = false;
resp.Message = ex.Message;
}
return resp;
}
This would complicate the refactoring, as the original methods actually had output parameters for bool success and string message; but it seems this can be accomplished in a decent and quick manner using a Tuple<>; otherwise we could just create a return type model.
To do this properly, there would be many hundreds of methods to refactor; quite an undertaking.
Would this work as expected, and be the best solution to accomplish the objective?
Is it likely worth all of the effort required, with the end goal of increasing scalability and subsequently "performance" of the web servers?
Would it be worth creating an async helper method that would expose a awaitable Task return type?
Nope.
The proposal is to create a helper method of the following
This just queues in-memory work to the thread pool.
(Side note: The task constructor should never be used. Ever. If you need to queue work to the thread pool, use Task.Run instead of the task constructor with Start)
Would this work as expected, and be the best solution to accomplish the objective?
Is it likely worth all of the effort required, with the end goal of increasing scalability and subsequently "performance" of the web servers?
These are the same question. The objective is scalability; asynchrony is just one means to help you accomplish it.
Asynchrony assists scalability on ASP.NET because it frees up a thread that can process other requests. However, if you make methods that are asynchronous by using another thread, then that doesn't assist you at all. I call this "fake asynchrony" - these kinds of methods look asynchronous but they're really just synchronously running on the thread pool.
In contrast to true asynchrony, fake asynchrony will actually hurt your scalability.
As this is a memory cache and Im saying this out of any direct experience with NCache but experiences with other cache systems.
Yes, this would work of course. I'd rather opt for a response struct or a generic class that allows me to define my response type (if it's possible at all). Tuples are not bad, probably would be more performant if you opt for classes instead. But they are not easy on the eyes.
Now, when it comes to performance, there is one question though. Here's a cache server for you and you want fast read-write of course. Accessing a memcache should be easy. As you're directly accessing the memory here, from a performance point of view, it won't really give you much. Are you making sure your code is fully async and you're using the threadpool properly to make things alright? Yes, of course but all it would ever do is add an extra layer or work when you're accessing your cache.
And the moment you're going for async, please do make sure that your memory cache is thread safe. :)
So one of my colleagues was saying to me -
"Why would somebody want to call async RestAPIs with thread, Its not beneficial and in return it will create a separate thread for every request."
My scenario is-
public async Task<ApiResponse<ProductLookupDto>> GetProductsByValueOfTheDay()
{
string url = "http://domain.com?param=10120&isBasic=true"
var result = Task.Run(() => JsonConvert.DeserializeObject<ProductLookupDto>(SerializedResults.GET(url)));
return new ApiResponse<ProductLookupDto>()
{
Data = await result,
Message = "success"
};
}
So here I am using async with threading. I know it will create a separate thread for request. Which is my concern about the performance.
I want to know if some of my methods are called together and if reponse is async as I am doing now. Will the thread affect to performance?
keeping in mind where - response from rest call is too large.
Your friend actually is not really knowing what he talks about - a Task will NOT create a separate thread for every request. Rather the task scheduler will determine threads - and the standard uses the thread pool. Which means that threads are pre allocated and reused, especially if you schedule a LOT of tasks. Also threads are released while the request runs due to completion ports. Your colleague shows a serious lack of basics here.
I think your colleague is right to be concerned with that code, and you are right to say "it pretends to be async but not really". And Jon Skeet is right to point out that the real problem here lies with SerializedResults.GET. Whatever the implentation of that is exactly, it's clearly a blocking call, otherwise it would return a Task<string> (that can be awaited) instead of a string. Wrapping a synchronous call in Task.Run and calling it asynchronous is a common mistake. You haven't eliminated blocking at all, you've simply moved the blocking call to a different thread.
So to make this asynchronous, SerializedResults.GET needs to go. It should be replaced by a call that uses a truly asynchronous library like HttpClient. Since this is a JSON API (and I'm a little bit biased), I'll show you an example using my Flurl library, which is basically a wrapper around HttpClient and Json.NET that provides some convenience methods to cut down on the noise a bit:
public async Task<ApiResponse<ProductLookupDto>> GetProductsByValueOfTheDay()
{
string url = "http://domain.com?param=10120&isBasic=true";
var result = await url.GetJsonAsync<ProductLookupDto>();
return new ApiResponse<ProductLookupDto>()
{
Data = result,
Message = "success"
};
}