I have method like that:
public async Task<IEnumerable<Model>> Get([FromUri]IList<string> links)
{
IList<Model> list = new List<Model>();
foreach (var link in links)
{
MyRequestAsync request = new MyRequestAsync(link);
list.Add(await request.GetResult());
}
return list;
}
But I am just wondering if it is really async because I am thinking that part list.Add(await request.GetResult()); and return list; breaking the async nature of the method.
Please correct me if I am wrong and if I am right how can I fix that?
UPDATED: for my understanding I have to so something like that C# 5.0 async await return a list return await Task.Run(() => new List<string>() {"a", "b"}); but not sure how to apply that for my case.
Your method is async, but may not be making the best use of resources.
What your method will do is enter the foreach loop, create the MyRequestAsync object, and then (at the await point) it will give up its thread until the result becomes available. Once the result is available, an appropriate thread will be found and the method will resume running. It will add the result to list and go back to the top of the loop, and repeat this whole process over and over.
But, consider this - if these requests are independent, you could, instead, make each of the requests in parallel, and then only continue running your method once all of the requests are complete. That would be something like:
public async Task<IEnumerable<Model>> Get([FromUri]IList<string> links)
{
IList<Task<Model>> list = new List<Task<Model>>();
foreach (var link in links)
{
MyRequestAsync request = new MyRequestAsync(link);
list.Add(request.GetResult());
}
return new List<Model>(await Task.WhenAll(list));
//Or just
//return await Task.WhenAll(list);
//Since we don't need to return a list
}
And, for silly points, you could re-write the whole method as:
return await Task.WhenAll(from l in links select new RequestAsync(l).GetResult());
But that may make it less readable.
In my opinion the I/O is async so the method can be called "really async".
async is meant for I/O to not block the thread when it is waiting for something (here the result), but not when it is "doing something" (here the list.Add).
That's kind of impossible to tell because anything you call could be a blocking operation. If there's a blocking operation hidden somewhere this method will block as well. If you want to make a method non-blocking and/or only use scalable async IO you must review everything that you do and that you call.
That said your code looks like it is non-blocking because it uses await (instead of, say, Task.Wait). Simplifying things a bit, this method will return on the first await operation which is probably what do need.
Related
I'm calling an async method (LoginAsync) for Authorization.
UserObject = clienAuthenticationService.LoginAsync(sUser).Result;
if (UserObject != null)
{
// Proceed for further code;
}
else
{
// Show Error message of failed authentication;
}
As this is third party service, I need output of LoginAsync before I go to next line (If block).
Current code is working fine for me and I know it waits until LoginAsync is executed.
However, I'm getting recommendation to Replace this use of 'Task.Result' with 'await'.
Question : I'm not sure if my case is relevant for await, since I need kind of Synchronous execution of async method. Can someone please confirm if recommendation given to me is irrelevant in my case or there is way to call async method synchronously with await ?
EDIT : After comments, I modified my code to add await instead of .Result. Still, unable to read response from async method. Below is new code
public static async Task<bool> CallJimService(LoginUserClass sUser)
{
var result = clientJIMServiceCall.LoginAsync(sUser).ConfigureAwait(false);
LoginUserClass loginUserDetails = await result;
if (loginUserDetails != null && loginUserDetails.UserProperties != null && loginUserDetails.UserProperties.LoggedIn)
{
return true;
}
else
{
return false;
}
}
public static Boolean ValidateUserCredentails(string pstrUserName, string pstrPassWord)
{
LoginUserClass sUser = new LoginUserClass();
sUser.UserName = pstrUserName;
sUser.Password = pstrPassWord;
return CallJimService(sUser).Result; // Here I want to avoid using .Result.
}
Also, I don't want to change ValidateUserCredentails() to async. How Can I get through this?
The LoginAsync method is marked async, and returns a Task. This method is expected to have an asynchronous implementation. You cannot execute this method synchronously, because this method does not have a synchronous implementation. If the class you are using would provide a synchronous implementation of the Login operation, they would have to expose a Login method.
There is no guarantee that calling this method asynchronously will result in an asynchronous operation. Asynchronous methods may return synchronously if the state needs them to. For instance, AsyncLogin may return synchronously if you already have logged in. However, unless doing something extremely specific, there must be at least one execution path in the method that requires some asynchronous operation.
Recommendation given to you is not irrelevant.
You should not block on an async operation, especially using Task.Result. Asynchronous operations does not involve multithreading, and awaiting on a Task.Result may provoke a deadlock of your application, because your thread will be waiting on the Result and will not be able to respond to the async operation signaling completion.
You'd rather await the LoginAsync method asynchronously, making your method async as well.
If you are forced to call the LoginAsync method from a synchronous context, the correct implementation will depend on what exactly you are trying to achieve and what the LoginAsync method does.
If you are able to use await (that is if you are in an async method already), then use await.
UserObject = await clienAuthenticationService.LoginAsync(sUser);
Using await helps the code run synchronous(that is it preserves flow of control).
I will try to explain async usage through the following example, which has asynchronous execution flow, but synchronous control flow -
Following code runs out of sync (asynchronous that is) -
// Authenticate the user, but don't wait here while authenticating.
// Async part could be - Checking database for user details. (Network IO operation)
var UserAuthTask = LoginAsync();
// Prepare a layout or something to show when authentication fails. Don't show yet.
// Again, don't wait while preparing.
// Async part could be - Reading a render template file. (File IO operation)
var AuthFailScreen = PrepareFailScreenAsync();
// Similar to failure screen.
var AuthSuccessScreen = PrepareSuccessScreenAsync();
Now, we use await to synchronize the flow to our liking -
var UserAuthResult = await UserAuthTask;
if (UserAuthResult.Success)
{
var SuccessScreen = await AuthSuccessScreen;
SuccessScreen.Show();
}
else
{
var FailScreen = await AuthFailScreen;
FailScreen.Show();
}
You could await each of the tasks before, like var UserAuthTask = await LoginAsync();, but then you would lose the benefit of doing multiple things which could've been done while authenticating.
I am not sure about exception handling, but mix and match of async and sync code will likely cause issues.
Please correct me if I am wrong at any point. Thanks.
I know it's not a good practice to use an async void. But what if I don't want to wait for a result of a long running task?
I have a scenario where I need to insert some values to the database and return a result. But I don't need to wait to finish all the insert before returning an instance of an object.
If you look at the code below, there's a method that initializes the DataService. But during the initialization part it needs to insert code description and headers to the database. I would like to return the dataService and I don't care if the code description and headers are finished inserting.
async Task<DataService> InitializeAsync()
{
_dataService = new DataService();
await _dataService.InsertCodeDescriptionAsync();
await _dataService.InserHeadersAsync();
return _dataService;
}
I think I can do that by changing InsertCodeDescriptionAsync and InsertHeadersAsync to be an async void function. But that's not good according to some articles I read. So what would be the best thing to do in this scenario?
Update:
The goal is to initialize the dataService and do the insert in the background.
Well my suggested answer is two-fold:
Simple answer: If you don't need to await a task, then don't await it.
But the consequences will be that the execution contexts of your main code and your not awaited tasks will diverge and if an exception happens in either of the methods you'll never know in your code. I suppose you call the two methods for a reason and they do something that'll eventually be needed by your code but not right away?
If so then I would suggest to still use await even if you don't need the methods to complete right away. This will however guarantee that the methods have completed at some point and the performance impact is often minimal, especially in a multi-threading scenario, since that's when the async magic kicks in and frees a lot of CPU time while waiting.
If you want to have both speed and reliability you could do something like
(DataService, Task) InitializeAsync()
{
_dataService = new DataService();
var t = Task.WhenAll(_dataService.InsertCodeDescriptionAsync(), _dataService.InserHeadersAsync());
return (_dataService, t);
}
which will give you the dataService right away but also a Task that you can use to await the completion of your initialization methods when you need them to be completed.
don't await the tasks you don't want to wait for. something like below will work for you.
Task<DataService> InitializeAsync()
{
_dataService = new DataService();
_dataService.InsertCodeDescriptionAsync();
_dataService.InserHeadersAsync();
return Task.FromResult(_dataService);
}
You could get rid of async and await altogether:
DataService Initialize()
{
_dataService = new DataService();
var fireAndForgetTask1 = _dataService.InsertCodeDescriptionAsync();
var fireAndForgetTask2 = _dataService.InsertHeadersAsync();
return _dataService;
}
This way you avoid any compiler warnings, and communicate your intent to ignore the results of the tasks to future maintainers of your code.
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)
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.
I have a class where each method execute asynchronously, i.e. return a Task, but where each method should nevertheless wait for the completion of the preceding call.
Continuation, right?
Except that a task continuation takes a delegate (Action) in parameter, not another task.
I've tried different things and the best I could do to make it work is the following (to me quite complex) code:
private Task QueueTask(Func<Task> futureTask)
{
var completionSource = new TaskCompletionSource<int>();
_lastTask.ContinueWith(async t =>
{
try
{
await futureTask();
completionSource.SetResult(0);
}
catch (Exception ex)
{
completionSource.SetException(ex);
}
});
_lastTask = completionSource.Task;
return _lastTask;
}
Here _lastTask is a private member of my class. Since all calls are coming from the UI thread, I just keep the last task and put continuation on it.
As I said I find this code quite convoluted. Do you have a better suggestion?
To me, it seems like you're asking the wrong question. A queue of tasks like this is an unusual requirement. We don't know anything about the actual problem you're trying to solve, so we can't suggest better approaches.
ContinueWith is intended for dynamic parallel processing, so it doesn't quite fit in with async code. However, you can use ContinueWith paired with Unwrap to sort-of emulate the behavior of await (if you ignore how await interacts with the current context).
So you can simplify your queue of tasks solution as such:
private Task QueueTask(Func<Task> futureTask)
{
_lastTask = _lastTask.ContinueWith(t => futureTask()).Unwrap();
return _lastTask;
}
However, there are probably better solutions. If the purpose of the queue is to provide exclusive access, a SemaphoreSlim would be more natural. If you actually do need a queue for some reason, consider using a Dataflow mesh.