I have a WPF form with several tabs on in. When I load the form I am also trying to load some data in the background for some of the tabs.
The code looks like this:
public static List<MyModel> GetCaseNotes(int someId)
{
return GetCaseNotesAsync(debtorId).Result;
}
public static async Task<List<MyModel>> GetCaseNotesAsync(int someId)
{
Task<List<MyModel>> tsk = Task.Run(() => GetCaseNotesFromDb(someId));
return await tsk.ConfigureAwait(false);
}
public static List<MyModel> GetCaseNotesFromDb(int debtorId)
{
//get some data from database
}
However, the UI is still waiting for the data to be taken from database... Any ideas?
Result will block until the task completes. You've avoided the deadlock I describe on my blog by using ConfigureAwait, but you're still explicitly blocking.
When loading data asynchronously, you'll need to design in a "loading" state for your UI and update it when the loading completes. I have another blog entry on asynchronous construction/initialization that you may find useful, in particular my NotifyTaskCompletion type attempts to make tasks more data-binding-friendly.
return GetCaseNotesAsync(debtorId).Result;
should be
return await GetCaseNotesAsync(debtorId);
When you call Result on a Task, you wait synchronously for the result, not asynchronously.
Because you have async method but calling it synchronously. Calling Async method without await will cause it to behave as a synchronous method.
In order to call it asynchronously you should call it like this
return await GetCaseNotesAsync(debtorId);
Related
Consider an API that returns Tasks with some values.
I want to update the UI based on that values in parallel (when one of the values is ready I want to update it without waiting for the second one assuming the update of each value as its own update method).
public async Task MyFunc()
{
Task<First> firstTask = MyAPI.GetFirstValue();
Task<Second> secondTask = MyAPI.GetSecondValue();
UpdateFirstValueUI(await firstTask)
UpdateSecondValueUI(await secondTask)
}
the code example will wait for the first value, update the UI, wait for the second value and update the UI again.
What is the best practice for that scenario? I was wondering if ContinueWith is best practice because I mostly see it in legacy code (before there was async-await).
edit with a better example:
assuming we have two implementations of that API and the code looks like that
public async Task MyFunc()
{
Task<First> firstTask = null
Task<Second> secondTask = null
if (someCondition)
{
firstTask = MyAPI1.GetFirstValue();
secondTask = MyAPI1.GetSecondValue();
}
else
{
firstTask = MyAPI2.GetFirstValue();
secondTask = MyAPI2.GetSecondValue();
}
UpdateFirstValueUI(await firstTask)
UpdateSecondValueUI(await secondTask)
}
now as you see I don't want call the update methods in two different branches (assuming we split that method for each API after the branching)
so looking for a way to change only the update calls so they could happen in parallel
The ContinueWith is a primitive method that has some rare uses in library code, and should generally be avoided in application code. The main problem with using the ContinueWith in your case is that it's going to execute the continuation on a ThreadPool, which is not what you want, because your intention is to update the UI. And updating the UI from any other thread than the UI thread is a no no. It is possible to solve this¹ problem by configuring the ContinueWith with a suitable TaskScheduler, but it's much simpler to solve it with async/await composition. My suggestion is to add the Run method below in some static class in your project:
public static class UF // Useful Functions
{
public static async Task Run(Func<Task> action) => await action();
}
This method just invokes and awaits the supplied asynchronous delegate. You could use this method to combine your asynchronous API calls with their UI-updating continuations like this:
public async Task MyFunc()
{
Task<First> task1;
Task<Second> task2;
if (someCondition)
{
task1 = MyAPI1.GetFirstValueAsync();
task2 = MyAPI1.GetSecondValueAsync();
}
else
{
task1 = MyAPI2.GetFirstValueAsync();
task2 = MyAPI2.GetSecondValueAsync();
}
Task compositeTask1 = UF.Run(async () => UpdateFirstValueUI(await task1));
Task compositeTask2 = UF.Run(async () => UpdateSecondValueUI(await task2));
await Task.WhenAll(compositeTask1, compositeTask2);
}
This will ensure that the UI will be updated immediately after each asynchronous operation completes.
As a side note, if you have any suspicion that the MyAPI asynchronous methods may contain blocking code, you could offload them to the ThreadPool by using the Task.Run method, like this:
task1 = Task.Run(() => MyAPI1.GetFirstValueAsync());
For a thorough explanation about why this is a good idea, you can check out this answer.
The difference between the built-in Task.Run method and the custom UF.Run method presented above, is that the Task.Run invokes the asynchronous delegate on the ThreadPool, while the UF.Run invokes it on the current thread. If you have any idea about a better name than Run, please suggest. :-)
¹ The ContinueWith comes with a boatload of other problems as well, like wrapping errors in AggregateExceptions, making it easy to swallow exceptions by mistake, making it hard to propagate the IsCanceled status of the antecedent task, making it trivial to leak fire-and-forget tasks, requiring to Unwrap nested Task<Task>s created by async delegates etc.
I have a multi-tier .Net 4.5 application calling a method using C#'s new async and await keywords that just hangs and I can't see why.
At the bottom I have an async method that extents our database utility OurDBConn (basically a wrapper for the underlying DBConnection and DBCommand objects):
public static async Task<T> ExecuteAsync<T>(this OurDBConn dataSource, Func<OurDBConn, T> function)
{
string connectionString = dataSource.ConnectionString;
// Start the SQL and pass back to the caller until finished
T result = await Task.Run(
() =>
{
// Copy the SQL connection so that we don't get two commands running at the same time on the same open connection
using (var ds = new OurDBConn(connectionString))
{
return function(ds);
}
});
return result;
}
Then I have a mid level async method that calls this to get some slow running totals:
public static async Task<ResultClass> GetTotalAsync( ... )
{
var result = await this.DBConnection.ExecuteAsync<ResultClass>(
ds => ds.Execute("select slow running data into result"));
return result;
}
Finally I have a UI method (an MVC action) that runs synchronously:
Task<ResultClass> asyncTask = midLevelClass.GetTotalAsync(...);
// do other stuff that takes a few seconds
ResultClass slowTotal = asyncTask.Result;
The problem is that it hangs on that last line forever. It does the same thing if I call asyncTask.Wait(). If I run the slow SQL method directly it takes about 4 seconds.
The behaviour I'm expecting is that when it gets to asyncTask.Result, if it's not finished it should wait until it is, and once it is it should return the result.
If I step through with a debugger the SQL statement completes and the lambda function finishes, but the return result; line of GetTotalAsync is never reached.
Any idea what I'm doing wrong?
Any suggestions to where I need to investigate in order to fix this?
Could this be a deadlock somewhere, and if so is there any direct way to find it?
Yep, that's a deadlock all right. And a common mistake with the TPL, so don't feel bad.
When you write await foo, the runtime, by default, schedules the continuation of the function on the same SynchronizationContext that the method started on. In English, let's say you called your ExecuteAsync from the UI thread. Your query runs on the threadpool thread (because you called Task.Run), but you then await the result. This means that the runtime will schedule your "return result;" line to run back on the UI thread, rather than scheduling it back to the threadpool.
So how does this deadlock? Imagine you just have this code:
var task = dataSource.ExecuteAsync(_ => 42);
var result = task.Result;
So the first line kicks off the asynchronous work. The second line then blocks the UI thread. So when the runtime wants to run the "return result" line back on the UI thread, it can't do that until the Result completes. But of course, the Result can't be given until the return happens. Deadlock.
This illustrates a key rule of using the TPL: when you use .Result on a UI thread (or some other fancy sync context), you must be careful to ensure that nothing that Task is dependent upon is scheduled to the UI thread. Or else evilness happens.
So what do you do? Option #1 is use await everywhere, but as you said that's already not an option. Second option which is available for you is to simply stop using await. You can rewrite your two functions to:
public static Task<T> ExecuteAsync<T>(this OurDBConn dataSource, Func<OurDBConn, T> function)
{
string connectionString = dataSource.ConnectionString;
// Start the SQL and pass back to the caller until finished
return Task.Run(
() =>
{
// Copy the SQL connection so that we don't get two commands running at the same time on the same open connection
using (var ds = new OurDBConn(connectionString))
{
return function(ds);
}
});
}
public static Task<ResultClass> GetTotalAsync( ... )
{
return this.DBConnection.ExecuteAsync<ResultClass>(
ds => ds.Execute("select slow running data into result"));
}
What's the difference? There's now no awaiting anywhere, so nothing being implicitly scheduled to the UI thread. For simple methods like these that have a single return, there's no point in doing an "var result = await...; return result" pattern; just remove the async modifier and pass the task object around directly. It's less overhead, if nothing else.
Option #3 is to specify that you don't want your awaits to schedule back to the UI thread, but just schedule to the thread pool. You do this with the ConfigureAwait method, like so:
public static async Task<ResultClass> GetTotalAsync( ... )
{
var resultTask = this.DBConnection.ExecuteAsync<ResultClass>(
ds => return ds.Execute("select slow running data into result");
return await resultTask.ConfigureAwait(false);
}
Awaiting a task normally would schedule to the UI thread if you're on it; awaiting the result of ContinueAwait will ignore whatever context you are on, and always schedule to the threadpool. The downside of this is you have to sprinkle this everywhere in all functions your .Result depends on, because any missed .ConfigureAwait might be the cause of another deadlock.
This is the classic mixed-async deadlock scenario, as I describe on my blog. Jason described it well: by default, a "context" is saved at every await and used to continue the async method. This "context" is the current SynchronizationContext unless it it null, in which case it is the current TaskScheduler. When the async method attempts to continue, it first re-enters the captured "context" (in this case, an ASP.NET SynchronizationContext). The ASP.NET SynchronizationContext only permits one thread in the context at a time, and there is already a thread in the context - the thread blocked on Task.Result.
There are two guidelines that will avoid this deadlock:
Use async all the way down. You mention that you "can't" do this, but I'm not sure why not. ASP.NET MVC on .NET 4.5 can certainly support async actions, and it's not a difficult change to make.
Use ConfigureAwait(continueOnCapturedContext: false) as much as possible. This overrides the default behavior of resuming on the captured context.
I was in the same deadlock situation but in my case calling an async method from a sync method, what works for me was:
private static SiteMetadataCacheItem GetCachedItem()
{
TenantService TS = new TenantService(); // my service datacontext
var CachedItem = Task.Run(async ()=>
await TS.GetTenantDataAsync(TenantIdValue)
).Result; // dont deadlock anymore
}
is this a good approach, any idea?
Just to add to the accepted answer (not enough rep to comment), I had this issue arise when blocking using task.Result, event though every await below it had ConfigureAwait(false), as in this example:
public Foo GetFooSynchronous()
{
var foo = new Foo();
foo.Info = GetInfoAsync.Result; // often deadlocks in ASP.NET
return foo;
}
private async Task<string> GetInfoAsync()
{
return await ExternalLibraryStringAsync().ConfigureAwait(false);
}
The issue actually lay with the external library code. The async library method tried to continue in the calling sync context, no matter how I configured the await, leading to deadlock.
Thus, the answer was to roll my own version of the external library code ExternalLibraryStringAsync, so that it would have the desired continuation properties.
wrong answer for historical purposes
After much pain and anguish, I found the solution buried in this blog post (Ctrl-f for 'deadlock'). It revolves around using task.ContinueWith, instead of the bare task.Result.
Previously deadlocking example:
public Foo GetFooSynchronous()
{
var foo = new Foo();
foo.Info = GetInfoAsync.Result; // often deadlocks in ASP.NET
return foo;
}
private async Task<string> GetInfoAsync()
{
return await ExternalLibraryStringAsync().ConfigureAwait(false);
}
Avoid the deadlock like this:
public Foo GetFooSynchronous
{
var foo = new Foo();
GetInfoAsync() // ContinueWith doesn't run until the task is complete
.ContinueWith(task => foo.Info = task.Result);
return foo;
}
private async Task<string> GetInfoAsync
{
return await ExternalLibraryStringAsync().ConfigureAwait(false);
}
quick answer :
change this line
ResultClass slowTotal = asyncTask.Result;
to
ResultClass slowTotal = await asyncTask;
why? you should not use .result to get the result of tasks inside most applications except console applications if you do so your program will hang when it gets there
you can also try the below code if you want to use .Result
ResultClass slowTotal = Task.Run(async ()=>await asyncTask).Result;
I have a program which has no purpose but to help me understand how async and await works. It's a console application which parses XML and waits for a name to be returned, either the surname or the first name. Here is the code:
static void Main(string[] args)
{
Task<string> name = GetFirstParsedName();
name.Wait();
if (name.IsCompleted)
{
Console.WriteLine(name.Result);
}
Console.ReadLine();
}
static async Task<string> GetFirstParsedName()
{
string xmlSnippet = #"<person>
<FirstName>Chamir</FirstName>
<Surname>Bodasing</Surname>
<Gender>Male</Gender>
<Nationality>South African</Nationality></person>";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlSnippet);
XmlParser xmlParser = new XmlParser();
Task<string> t_GetFirstName = xmlParser.GetFirstName(xmlDoc);
Task<string> t_GetSurname = xmlParser.GetSurname(xmlDoc);
Task<string> t_firstReturnedName = await Task.WhenAny(new Task<string>[] { t_GetFirstName, t_GetSurname });
string firstReturnedName = await t_firstReturnedName;
return firstReturnedName;
}
static async Task<string> GetFirstName(XmlDocument personXml)
{
string firstName = personXml.SelectSingleNode("//FirstName").InnerText;
await Task.Delay(5000);
return firstName;
}
static async Task<string> GetSurname(XmlDocument personXml)
{
string surname = personXml.SelectSingleNode("//Surname").InnerText;
await Task.Delay(1);
return surname;
}
It seems like it only makes sense to use the async method when you don't have to return a value to a main method. Unless it means setting a global class property which can then be accessed. If not, in order to await the method, all methods need to be async which in turn means that the return type must be Task<T>. It seems like it never ends unless I explicitly have to write the following code (as in above main method):
Task<string> name = GetFirstParsedName();
name.Wait();
if (name.IsCompleted)
{
Console.WriteLine(name.Result);
}
Is my understanding correct at all? I have to use the result property to get the value here and from reading up about this, it seems that this is not the best practice.
It seems like it only makes sense to use the async method when you don't have to return a value to a main method. Unless it means setting a global class property which can then be accessed.
Your async methods can return Task<T> to return a value to its caller. Asynchronous methods do not work very well if they depend on side effects (i.e., setting properties / globals); they work much better if your code is more pure (i.e., taking parameters and returning results).
If not, in order to await the method, all methods need to be async which in turn means that the return type must be "Task" . It seems like it never ends
This is why one of the central principles of async is "async all the way". In most applications, this is exactly what you should do. Eventually, the "async chain" generally ends in an async void event handler (for UI apps) or an async Task<T> entry point (for ASP.NET apps). Console apps are unusual since they do require an explicit Wait()/Result or equivalent in their Main method.
After all, the whole point of async is to free up the calling thread. If the next method up the call stack blocks that same thread until the async code is complete, well, that was a whole lot of work for no benefit...
It seems like it only makes sense to use the async method when you don't have to return a value to a main method.
Why do you say that? It makes sense to use an async method where-ever you have a naturally asynchronous operation ongoing. No matter if that operation has a return value or doesn't.
in order to await the method, all methods need to be async which in turn means that the return type must be "Task" . It seems like it never ends
That's correct. Async spreads in your code like a plage, from the bottom to the top of your stack. It usually reaches the highest calling place in your stack (be it a console Main method or a UI event handler). That's the advantage of using async, it allows you to asynchronously wait an operation while freeing the calling thread. This can help, for example, if you have a WebAPI endpoint which needs to handle a large amount of requests concurrently. If you spend most of your time querying a database, you can free that calling thread in the meanwhile to serve more requests.
Is my understanding correct at all? I have to use the result property to get the value here and from reading up about this, it seems that this is not the best practice.
You have to use the Result property because a console application is a special case, where Main cant be marked as async (unless you're using ASP.NET CoreCLR console app). If this was a UI event handler or an ASP.NET action, you'd properly await the async call.
Well, async keyword let's compiler know that your method is going to execute series of asynchronous calls that should most likely be awaited but should not block the main (or UI) thread.
To help you understand async-await a little bit, here is some simple example:
Consider the scenario, when user clicks 'Save' button on WinForm's app, and some UI operation is started asynchronously in different Thread.
The code is :
private Task SomeUIOperation()
{
// ui operation
return Task.Run(() =>
{
this.Invoke(new Action(() => this.BackColor = Color.Aquamarine));
Thread.Sleep(10000);
this.Invoke(new Action(() => this.BackColor = Color.Gray));
});
}
private async void button1_Click(object sender, EventArgs e)
{
await SomeUIOperation();
// some other stuff
}
If we do not use async-await here UI thread will become unresponsive for 10 seconds.
It's an example of how you usually use async-await, you use it when you want some piece of code to be executed only when asynchronous operation is completed and in the same time you do not want the main thread to be blocked.
And console application is not the best project type for testing and learning Async-Await
I have a method in my view model
private async void SyncData(SyncMessage syncMessage)
{
if (syncMessage.State == SyncState.SyncContacts)
{
this.SyncContacts();
}
}
private async Task SyncContacts()
{
foreach(var contact in this.AllContacts)
{
// do synchronous data analysis
}
// ...
// AddContacts is an async method
CloudInstance.AddContacts(contactsToUpload);
}
When I call SyncData from the UI commands and I'm syncing a large chunk of data UI freezes. But when I call SyncContacts with this approach
private void SyncData(SyncMessage syncMessage)
{
if (syncMessage.State == SyncState.SyncContacts)
{
Task.Run(() => this.SyncContacts());
}
}
Everything is fine. Should not they be the same?
I was thinking that not using await for calling an async method creates a new thread.
Should not they be the same? I was thinking that not using await for
calling an async method creates a new thread.
No, async does not magically allocate a new thread for it's method invocation. async-await is mainly about taking advantage of naturally asynchronous APIs, such as a network call to a database or a remote web-service.
When you use Task.Run, you explicitly use a thread-pool thread to execute your delegate. If you mark a method with the async keyword, but don't await anything internally, it will execute synchronously.
I'm not sure what your SyncContacts() method actually does (since you haven't provided it's implementation), but marking it async by itself will gain you nothing.
Edit:
Now that you've added the implementation, i see two things:
I'm not sure how CPU intensive is your synchronous data analysis, but it may be enough for the UI to get unresponsive.
You're not awaiting your asynchronous operation. It needs to look like this:
private async Task SyncDataAsync(SyncMessage syncMessage)
{
if (syncMessage.State == SyncState.SyncContacts)
{
await this.SyncContactsAsync();
}
}
private Task SyncContactsAsync()
{
foreach(var contact in this.AllContacts)
{
// do synchronous data analysis
}
// ...
// AddContacts is an async method
return CloudInstance.AddContactsAsync(contactsToUpload);
}
What your line Task.Run(() => this.SyncContacts()); really does is creating a new task starting it and returning it to the caller (which is not used for any further purposes in your case). That's the reason why it will do its work in the background and the UI will keep working. If you need to (a)wait for the task to complete, you could use await Task.Run(() => this.SyncContacts());. If you just want to ensure that SyncContacts has finished when you return your SyncData method, you could using the returning task and awaiting it at the end of your SyncData method. As it has been suggested in the comments: If you're not interested in whether the task has finished or not you just can return it.
However, Microsoft recommend to don't mix blocking code and async code and that async methods end with Async (https://msdn.microsoft.com/en-us/magazine/jj991977.aspx). Therefore, you should consider renaming your methods and don't mark methods with async, when you don't use the await keyword.
Just to clarify why the UI freezes - the work done in the tight foreach loop is likely CPU-bound and will block the original caller's thread until the loop completes.
So, irrespective of whether the Task returned from SyncContacts is awaited or not, the CPU bound work prior to calling AddContactsAsync will still occur synchronously on, and block, the caller's thread.
private Task SyncContacts()
{
foreach(var contact in this.AllContacts)
{
// ** CPU intensive work here.
}
// Will return immediately with a Task which will complete asynchronously
return CloudInstance.AddContactsAsync(contactsToUpload);
}
(Re : No why async / return await on SyncContacts- see Yuval's point - making the method async and awaiting the result would have been wasteful in this instance)
For a WPF project, it should be OK to use Task.Run to do the CPU bound work off the calling thread (but not so for MVC or WebAPI Asp.Net projects).
Also, assuming the contactsToUpload mapping work is thread-safe, and that your app has full usage of the user's resources, you could also consider parallelizing the mapping to reduce overall execution time:
var contactsToUpload = this.AllContacts
.AsParallel()
.Select(contact => MapToUploadContact(contact));
// or simpler, .Select(MapToUploadContact);
I have a view model that is fetching a row of records and displaying on the Windows phone UI.. This view model method which fetches the data is doing a lot of Tasks, all marked with Await operations..
Looks like below:
async Task GetData()
{
var dataCollection = await GetSomeData();
await DoThis();
await DoThat();
}
The UI refreshes after the 'DoThis' call is invoked.
Now I just observed that if I introduce a Task.Delay in the code before other Tasks are done, the UI is refreshed immediately.. Which was my original Goal, to refresh the UI immediately after 'GetSomeData' Returns and then fire the other Tasks.
Looks like below:
async Task GetData()
{
var dataCollection = await GetSomeData();
await Task.Delay(100);
await DoThis();
await DoThat();
}
So what I understand from this, is that the UI thread gets opportunity to refresh after a call to Task.Delay is made. However without Task.Delay, if DoThis is called, some time is lost before it finds the first awaitable method in 'DoThis' so that it can return and continue with UI Refresh.
My questions are:
Have I understood it correct?
Is it safe to put this in production code?
Thanks in advance and hope I have explained clearly..
Pr
Below is Details of These methods as without those it is not clear what is going in the program.. :(
async Task<ObservableCollection<MyModel>> GetSomeData()
{
return await Task.Run(() =>
{
using (var db = new MainModelDataContext())
{
List<MyModel> temp =
db.Models.Where(Some condition)
.Take(30)
.ToList();
var returnCollection = new ObservableCollection<MyModel>(temp);
return returnCollection;
}
}
The ObservableCollection is bound to a list control on the UI Page. This method is being called by the page view model.
async Task DoThis()
{
// do some data processing and then post that to the Server
// this is the first awaitable method after the data processing
await (an HttpClientHandler).PostAsync();
}
Task DoThat() also follows the same flow as DoThis.. The data processing is also wrapped in async-await Tasks and they are just working on some class properties.
Hope I am clear.. Thanks again all
When you call Task.Delay, you return control to the UI message loop for those 100 milliseconds, and the UI message loop has the opportunity to process more messages from its queue. That's why you're experiencing the "refreshing" effect. If your GetSomeData method is truely asynchronous, your UI should remain responsive during its operation, and when it completes, it will continue to execute the next await.
If this effect doesn't happen, then that means your methods aren't really asynchronous, and its more likely that they are running a costly operation in a synchronous fashion which is blocking your UI thread.
Before putting this into production, you have to look into why you need Task.Delay to refresh your UI.