Running synchronous method async - c#

I have a method that iterates a list of objects and for each item in the list fetches data from an external api.
Sometimes this can be very slow (naturally) and I'd like to add all my items to a Taks list instead to be able to run multiple threads at the same time. Is this possible without rewriting it all to be async? Today I'm using WebClient and fetches everything synchronously.
I tried something like this at first:
public Main()
{
List<Task<Model>> taskList = new List<Task<Model>>();
foreach (var aThing in myThings)
{
taskList.Add(GetStuffAsync(aThing));
}
List<Model> list = Task.WhenAll(taskList.ToArray()).Result.ToList();
}
public async Task<Model> GetStuffAsync(object aThing)
{
// Stuff that is all synchronous
// ...
return anObject;
}

Rather than using async here, you can just make GetStuff a normal synchronous method and use Task.Run to create new tasks (which will normally be run on multiple threads) so that your fetches occur in parallel. You could also consider using Parallel.ForEach and the like, which is effectively similar to your current Main code.
Your async approach will not do what you want at the moment, because async methods run synchronously at least as far as the first await expression... in your case you don't have any await expressions, so by the time GetStuffAsync returns, it's already done all the actual work - you have no parallelism.
Of course, an alternative is to use your current code but actually do make GetStuffAsync asynchronous instead.
It's also worth bearing in mind that the HTTP stack in .NET has per-host connection pool limits - so if you're fetching multiple URLs from the same host, you may want to increase those as well, or you won't get much parallelism.

Try this concept:
foreach(var aThing in myThings)
{
Thread myTask = new Thread(new ParameterizedThreadStart(TaskMethod));
myTask.Start(aThing);
}
and there must be a method called TaskMethod that is void TaskMethod(object obj)

Related

async or not async method

I am writing a blazor server web application.
This application works with a database and Entity Framework.
Here is a method i've wrote:
private void MyMethod()
{
var query = mydbcontext.mytable1.Where(t => ...);
foreach (var item in query)
{
...
}
}
As you can see this method is not declared with "async Task". So she will be called without "await" keyword.
I can declare it with "async Task" and call it with "await". It works but it gives me a warning because i have no async call inside.
Let's suppose i decide to not declare it with "async Task" in order to avoid the warning.
What will happen if i need to change something in my function later which needs an Async call (For example this):
private async Task MyMethod()
{
var query = mydbcontext.mytable1.Where(t => ...);
foreach (var item in query)
{
...
}
var countresult = await query.CountAsync();
}
I will need to search all calls of MyMethod and add "await" on each of this calls.
To prevent that, I am wondering if i should not declare all my methods with "async Task". But this is ugly because i will get warnings.
What is the best practice ?
And is there a way to do this loop as ASync ?
private async Task MyMethod()
{
var query = mydbcontext.mytable1.Where(t => ...);
await foreachAsync (var item in query)
{
...
}
var countresult = await query.CountAsync();
}
Thanks
... I am wondering if i should not declare all my methods with "async Task".
If there is no I/O being performed by the method then there is no need to make the method return a Task or Task<T> and by extension no need to use the async keyword.
If the method does do operations that use I/O (like a database call) then you have a couple of options and what you choose depends on the context your code is being used in.
When to use Asynchronous Operations
If the context can benefit from using asynchronous I/O operations, like the context of a web application, then your methods should return Task or Task<T>. The benefit of using asynchronous I/O is that threads are not locked waiting on I/O to complete which is important in applications that need to service many simultaneous requests that are thread resource intensive (like a web application). A windows forms or wpf application is also applicable because it allows for easy coding so the main thread can resume operations while I/O completes (the ui won't appear frozen).
When not to use Asynchronous Operations
If the context cannot benefit from using asynchronous I/O operations then make all your methods synchronous and do not return Task or Task<T>. An example of this would be a console application or a windows service application. You mentioned a Blazor web application in your question so this scenario does not appear to apply to you.
Provide both Asynchronous Operations and Synchronous Operations
If you want to allow the caller to choose then you can include 2 variations for each call that executes an I/O operation. A good example of this are the extensions written for Entity Framework. Almost all of the operations can be performed asynchronously or synchronously. Examples include Single/SingleAsync, All/AllAsync, ToArray/ToArrayAsync, etc.
This approach will also allow you to extend a public method later by adding an async overload if you extend the operation to include an I/O call at a future point in time. There are ways to do this without creating too much code duplication. See Async Programming - Brownfield Async Development by Stephen Cleary for various techniques. My favorite approach is the The Flag Argument Hack.
Side note: If you do not need to consume the results of an I/O call in your method and there is only one I/O method you do not need to use the async/await keywords. You can return the result of the I/O operation directly.
private void MyMethod()
{
var query = mydbcontext.mytable1.Where(t => ...);
foreach (var item in query) // Here you will retrieve your data from the DB.
{
...
}
// If you're going to count it here, don't use the query. You already retrieved
// the data for your foreach.
}
It would be better to retrieve the data before the foreach. That way you will not call the DB twice for 1. the foreach, 2. the count. I.E.
private async Task MyMethod()
{
var data = await mydbcontext.mytable1.Where(t => ...).ToListAsync();
foreach (var item in data)
{
...
}
// Don't call the DB here. You already have the data, so just count the items in
// the list.
var countresult = await data.Count;
}

Understanding fire and forget when using infinite loops

Can someone tell me what the best practice/proper way of doing this is?
I'm also using WPF, not a console or ASP.NET.
Using Listener to accept clients and spin off a new "thread" for each client that handles all the I/O and Exception catching for that client.
Method 1: Fire and forget, and just throw it into a variable to get rid of the warning.
public static async Task Start(CancellationToken token)
{
m_server = TcpListener.Create(33777);
m_server.Start();
running = true;
clientCount = 0;
// TODO: Add try... catch
while (!token.IsCancellationRequested)
{
var client = await m_server.AcceptTcpClientAsync().ConfigureAwait(false);
Client c = new Client(client);
var _ = HandleClientAsync(c);
}
}
Here's the Client Handler code:
public static async Task HandleClientAsync(Client c)
{
// TODO: add try...catch
while (c.connected)
{
string data = await c.reader.ReadLineAsync();
// Now we will parse the data and update variables accordingly
// Just Regex and some parsing that updates variables
ParseAndUpdate(data);
}
}
Method 2: The same thing... but with Task.Run()
var _ = Task.Run(() => HandleClientAsync());
Method 3: an intermediate non async function (doubt this is good. Should be Async all the way)
But this at least gets rid of the squiggly line without using the variable trick which kinda feels dirty.
while (!token.IsCancellationRequested)
{
var client = await m_server.AcceptTcpClientAsync().ConfigureAwait(false);
Client c = new Client(client);
NonAsync(c);
}
public static void NonAsync(VClient vc)
{
Task.Run(() => HandleClientAsync(vc));
}
Method 4: Make HandleClientAsync an Async void instead of Async Task (really bad)
public static async Task HandleClientAsync(Client c)
// Would change to
public static async Void HandleClientAsync(Client c)
Questions:
Is it any better to use Task.Run() When doing a fire and forget task?
Is it just accepted that you need to use the var _ = FireAndForget() trick to do fire and forget? I could just ignore the warning but something feels wrong about it.
If I wanted to update my UI from a Client, how would I do that? Would I just use a dispatcher?
Thanks guys
I've never been a fan of background workers which you expect to run for a long time, being run in a task. Tasks get scheduled to run on threads drawn from a pool. As you schedule these long running tasks, the thread pool gets smaller and smaller. Eventually all of the threads from the pool are busy running your tasks, and things get really slow and unmanageable.
My recommendation here? Use the Thread class and manage them yourselves. In this way, you keep your thread pool and the overhead for for tasks out of the picture.
Addendum - Producer Consumer Model
Another interesting question to consider: Do you really need a thread for every client? Threads are reasonably costly to create and maintain in terms of memory overhead, and if your client interaction is such that the client threads spend the vast majority of their time waiting around on something to do, then perhaps a producer consumer model is more suited to your use case.
Example:
Client connects on listening thread, gets put in a client queue
Worker thread responsible for checking to see if the clients need anything comes along through that queue every so often and checks - does the client have a new message to service? If so, it services all messages the client has, then moves on
In this way, you limit the number of threads working to just the number needed to manage the message queue. You can even get fancy and add worker threads dynamically based on how long its been since all the clients have been serviced.
If you insist
If you really like what you have going, I suggest refactoring what youre doing a bit so that rather than HandleClientAsync you do something more akin to CreateServiceForClient(c);
This could be a synchronous method that returns something like a ClientService. ClientService could then create the task that does what your HandleClientAsync does now, and store that task as a member. It could also provide methods like
ClientService.WaitUntilEnd()
and
ClientService.Disconnect() (which could set a cancellation token, also stored as a member variable)

Parllel Foreach vs Async Foreach for DB calls

I have scenario where I have to call a same database stored procedure for each item in a list. I don't want to use foreach as it will degrade the performance, Which will be best option parllel foeach or async/await foreach?
Below is sample code
public Task<List<object>> CallMethod()
{
foreach(var obj in input)
{
List.Add(await Task.Run(() =>CallDatabase(obj)));
}
return List;
}
public CallDatabase(object)
{
//Code to call DB
}
All the objects received from the DB are independents.
After few research I am planning to use async calls, will this improve performance?
I'm not sure it's going to make any difference either way. I assume you still need to wait for all results to be loaded, in which case async does not help, and your bottleneck will most likely be network I/O and server processing rather than local CPU, so parallelism will not help either.
That said, if you don't need the results of the query and don't care if there is an error, then async may help in a fire-and-forget scenario.
Your biggest bang for your buck may be to try and get multiple results in one query rather than firing off a bunch of individual queries.
Defintiely Async, as Parallel.ForEach is meant for compute intensive operations. It spreads over available core resources and orchestrates them accordingly. Async, instead, is meant for just this kind of operations: make a request to the service, go ahead and receive notification once resources requested before are available.
This is mostly comment to D Stanley's answer - switching to parallel/async code unlikely to improve performance.
If your main concern is responsiveness/scalability - async would be better as generally DB access is IO-bound operation. It also allows to pick between sequential and parallel processing (i.e. in case your DB layer does not support concurrent requests on same connection for some reason). Additionally with async it is easier to get synchronization right for updating UI/request if you use default synchronization context.
Sequential: it will run about as long as non-async solution, but the thread will be free to perform other activities at the same time (for UI applications like WinForms/WPF) or process requests (ASP.Net).
async public Task<ResultType> CallMethodAsync()
{
foreach(var obj in input)
{
var singleResult = await CallDatabaseAsync(obj);
// combine results if needed
}
// return combined results
}
Parallel: will run all requests at the same time, will likely be faster than sequential solution.
async public Task<ResultType> CallMethodAsync()
{
List<Task<SingleResultType>> tasks = new List<Task<SingleResultType>>();
foreach(var obj in input)
{
tasks.Add(await CallDatabaseAsync(obj));
}
await Task.WhenAll(tasks);
foreach(SingleResultType result in tasks.Select(t=>t.Result))
{
// combine results if needed
}
// return combined results
}
Note that async generally requires all your code to be asynchronous - so if you converting just small piece of code to run in parallel Parallel.ForEach may be easier solution as it does not involve dealing with await vs Task.Wait - Deadlock?.
I have implemented a solution; not sure if this async or will improve performance a bit or not, I am very new to async so don't have much idea.
public static async Task<List<Response>> Execute(Request objInput)
{
List<Response> objList = new List<Response>();
foreach (object obj in objInput.objs)
{
objList.Add(await Task.Run(() =>GetDataFromDB(obj)));
}
return objList;
}
private static object GetDataFromDB(object obj)
{
//Call DB and build the object
}
If this is not the correct way to implement async, then please offer other ideas.

Load lists from Entity Framework without make the controller wait

I want to load a set of list at the begining of my Web App, to use them later. These lists are static and are read from the Data Base using Entity Framework as ORM. The idea is to load the list at the begining (on the home page after login) and use them all over de App. But I don't want that the home page was waiting for the list to finish loagind. I have tried several alternatives but no one works (or it goes sync or got errors).
1. First attempt: Calling ToListAsync() and Await to the ToListAsync (Throw Exception from EF)
There are two version of the list one async and other sync:
private static Task<List<EMPRESA>> ListaEmpresasAsync;
public static List<EMPRESA> ListaEmpresas
I have defined a function that generates the lists from the repository on EF
public async static Task<List<T>> GenerateAsyncListFromRepository(IGenericRepositoryBlockable<T> repository)
{
IQueryable<T> queryAsync = repository.GetAllActive();
return await queryAsync.ToListAsync();
}
And other one another function to check the result from the async calls:
public static List<T> ForceToLoadAsyncList(Task<List<T>> task)
{
task.Wait();
return task.Result;
}
The I async load the list:
ListaEmpresasAsync = TaskManager<EMPRESA>.GenerateAsynListFromRepository((IEmpresaRepositorio)DIResolver.GetService(typeof(IEmpresaRepositorio)));
And when the List is needed I force to load:
public static List<EMPRESA> ListaEmpresas
{
get
{
return TaskManager<EMPRESA>.ForceToLoadAsyncList(ListaEmpresasAsync);
}
}
This initial approach throws the following error:
A second operation started on this context before a previous asynchronous operation completed
2. Second: Use ToList() and await to the end of the Task.Run() (Problem with empty enumerables)
Then I tested to use ToList() instead ToListAsync:
return await Task.Run(() => { return queryAsync.ToList(); });
I doesn't work either.
3. Third: Use ToList() and await the GenerationList the Force just return the List (Behaviour similar to sync approach. The controller is waiting for all the lists loading)
Following this approach I change the signature of the funcion to return list:
return queryAsync.ToList();
And await on the load process
ListaEmpresasAsync = await TaskManager<EMPRESA>.GenerateAsynListFromRepository((IEmpresaRepositorio)DIResolver.GetService(typeof(IEmpresaRepositorio)));
But this is working similar to the sync process, that means that on the home page the loading time is really high.
I know that on EF, only one async call is allowed for each context. I just want to put all these loading process on the background even if they run sync, and when the list is needed check for the result of the task.
Any idea?
Just for clarification the solution proposed by Yuval Itzchakov should work when the DbContext is not shared among all the loading lists calls, but In my scenario it throws the error related to more than one async call on Entity Framework.
There are a couple of things wrong with your code.
First, you need to know that even when making an async call using async-await, the request doesn't complete until the awaited operation returns. This is significant, because if what you need is a Fire and Forget style operation, this wont do.
If you do want to execute asynchronously (not fire and forget), do the following:
public static List<EMPRESA> ListaEmpresas
public static Task<List<T>> GenerateAsyncListFromRepository(IGenericRepositoryBlockable<T> repository)
{
return repository.GetAllActive().ToListAsync();
}
And then call it like this:
ListaEmpresas = await TaskManager<EMPRESA>.GenerateAsyncListFromRepository((IEmpresaRepositorio)DIResolver.GetService(typeof(IEmpresaRepositorio)));
Making two lists and using Task.Wait is useless, you aren't forcing anything other then your thread waiting on the async method to return, which means it runs synchronously.
If what you want is Fire and Forget, note the following:
Using Task.Run in ASP.NET is dangerous, as it doesn't register the queued work with the ASP.NET ThreadPool, and is exposed to IIS recycling which may cause your background work to terminate unexpectedly. Instead, if you're using .NET 4.5.2 you can use HostingEnvironment.QueueBackgroundWorkItem which registers the queued task for you. If not, look into Stephan Clearys BackgroundTaskManager
You can do this parallel tasks with EF, however the intention of Using 1 DBContext in parallel threads will end in tears.
The instance members of DBContext are not thread safe ! DBContext info
You can use a simple pattern that spans threads
Thread n+1
Thread N+2
....
And await the result.
Each thread must use its own context.
I use this pattern to search many object types at once for a given search string.
But have have a wait to get the overall result is part of the design.
Not sure if that suits your requirement.
Parallel tasks demo
If you have non volatile data sets, you can get IIS to cache results.
I use this approach on a Controller Method with NON volatile content.
See the OutputCache Annotation.
[OutputCache(Duration = int.MaxValue, VaryByParam = "id", Location = OutputCacheLocation.ServerAndClient)]

Wrapping synchronous code into asynchronous call

I have a method in ASP.NET application, that consumes quite a lot of time to complete. A call to this method might occur up to 3 times during one user request, depending on the cache state and parameters that user provides. Each call takes about 1-2 seconds to complete. The method itself is synchronous call to the service and there is no possibility to override the implementation.
So the synchronous call to the service looks something like the following:
public OutputModel Calculate(InputModel input)
{
// do some stuff
return Service.LongRunningCall(input);
}
And the usage of the method is (note, that call of method may happen more than once):
private void MakeRequest()
{
// a lot of other stuff: preparing requests, sending/processing other requests, etc.
var myOutput = Calculate(myInput);
// stuff again
}
I tried to change the implementation from my side to provide simultaneous work of this method, and here is what I came to so far.
public async Task<OutputModel> CalculateAsync(InputModel input)
{
return await Task.Run(() =>
{
return Calculate(input);
});
}
Usage (part of "do other stuff" code runs simultaneously with the call to service):
private async Task MakeRequest()
{
// do some stuff
var task = CalculateAsync(myInput);
// do other stuff
var myOutput = await task;
// some more stuff
}
My question: Do I use the right approach to speed up the execution in ASP.NET application or am I doing unnecessary job trying to run synchronous code asynchronously?
Can anyone explain why the second approach is not an option in ASP.NET (if it is really not)?
Also, if such approach is applicable, do I need to call such method asynchronously if it is the only call we might perform at the moment (I have such case, when no other stuff there is to do while waiting for completion)?
Most of the articles in the net on this topic covers using async-await approach with the code, that already provides awaitable methods, but that's not my case. Here is the nice article describing my case, which doesn't describe the situation of parallel calls, declining the option to wrap sync call, but in my opinion my situation is exactly the occasion to do it.
It's important to make a distinction between two different types of concurrency. Asynchronous concurrency is when you have multiple asynchronous operations in flight (and since each operation is asynchronous, none of them are actually using a thread). Parallel concurrency is when you have multiple threads each doing a separate operation.
The first thing to do is re-evaluate this assumption:
The method itself is synchronous call to the service and there is no possibility to override the implementation.
If your "service" is a web service or anything else that is I/O-bound, then the best solution is to write an asynchronous API for it.
I'll proceed with the assumption that your "service" is a CPU-bound operation that must execute on the same machine as the web server.
If that's the case, then the next thing to evaluate is another assumption:
I need the request to execute faster.
Are you absolutely sure that's what you need to do? Are there any front-end changes you can make instead - e.g., start the request and allow the user to do other work while it's processing?
I'll proceed with the assumption that yes, you really do need to make the individual request execute faster.
In this case, you'll need to execute parallel code on your web server. This is most definitely not recommended in general because the parallel code will be using threads that ASP.NET may need to handle other requests, and by removing/adding threads it will throw the ASP.NET threadpool heuristics off. So, this decision does have an impact on your entire server.
When you use parallel code on ASP.NET, you are making the decision to really limit the scalability of your web app. You also may see a fair amount of thread churn, especially if your requests are bursty at all. I recommend only using parallel code on ASP.NET if you know that the number of simultaneous users will be quite low (i.e., not a public server).
So, if you get this far, and you're sure you want to do parallel processing on ASP.NET, then you have a couple of options.
One of the easier methods is to use Task.Run, very similar to your existing code. However, I do not recommend implementing a CalculateAsync method since that implies the processing is asynchronous (which it is not). Instead, use Task.Run at the point of the call:
private async Task MakeRequest()
{
// do some stuff
var task = Task.Run(() => Calculate(myInput));
// do other stuff
var myOutput = await task;
// some more stuff
}
Alternatively, if it works well with your code, you can use the Parallel type, i.e., Parallel.For, Parallel.ForEach, or Parallel.Invoke. The advantage to the Parallel code is that the request thread is used as one of the parallel threads, and then resumes executing in the thread context (there's less context switching than the async example):
private void MakeRequest()
{
Parallel.Invoke(() => Calculate(myInput1),
() => Calculate(myInput2),
() => Calculate(myInput3));
}
I do not recommend using Parallel LINQ (PLINQ) on ASP.NET at all.
I found that the following code can convert a Task to always run asynchronously
private static async Task<T> ForceAsync<T>(Func<Task<T>> func)
{
await Task.Yield();
return await func();
}
and I have used it in the following manner
await ForceAsync(() => AsyncTaskWithNoAwaits())
This will execute any Task asynchronously so you can combine them in WhenAll, WhenAny scenarios and other uses.
You could also simply add the Task.Yield() as the first line of your called code.
this is probably the easiest generic way in your case
return await new Task(
new Action(
delegate () {
// put your synchronous code here
}
)
);

Categories

Resources