Recursive WinRT Async Issues - c#

I have some code that does something like this:
abstract class Data
{
Data(string name, bool load) { if (load) { Load().Wait(); }
abstract Task Load();
}
class XmlData : Data
{
XmlData(string name, bool load = true) : base(name, load) {}
override async Task Load()
{
var file = await GetFileAsync(...);
var xmlDoc = await LoadXmlDocAsync(file);
ProcessXml(xmlDoc);
}
void ProcessXml(XmlDocument xmlDoc)
{
foreach (var element in xmlDoc.Nodes)
{
if (element.NodeName == "something")
new XmlData(element.NodeText);
}
}
}
I seem to (sometimes) get wierd timing issues, where it ends up hanging the code at GetFileAsync(...). Is this caused by the recursive nature of the calls? When I change all the await calls to actually do a .Wait() for them to finish, and essentially get rid of all the asynchronous nature of the calls, my code executes fine.

Is this caused by the recursive nature of the calls? When I change all the await calls to actually do a .Wait() for them to finish, and essentially get rid of all the asynchronous nature of the calls, my code executes fine.
It really depends -
The most likely culprit would be if your caller is somehow blocking the user interface thread (via a call to Wait(), etc). In this case, the default behavior of await is to capture the calling synchronization context, and post the results back on that context.
However, if a caller is using that context, you can get a deadlock.
This is very likely the case, and being caused by this line of code:
Data(string name, bool load) { if (load) { Load.Wait(); }
This can be easily avoided by making your library code (like this XmlData class) explicitly not use the calling synchronization context. This is typically only required for user interface code. By avoiding the capture, you do two things. First, you improve teh overall performance (often dramatically), and second, you avoid this dead lock condition.
This can be done by using ConfigureAwait and changing your code like so:
override async Task Load()
{
var file = await GetFileAsync.(...).ConfigureAwait(false);
var xmlDoc = await LoadXmlDocAsync(file).ConfigureAwait(false);
ProcessXml(xmlDoc);
}
That being said - I would rethink this design a bit. There are really two problems here.
First, your putting a virtual method call in your constructor, which is fairly dangerous, and should be avoided when possible, as it can lead to unusual problems.
Second, your turning your entire asynchronous operation into a synchronous operation by putting this in the constructor with the block. I would, instead, recommend rethinking this entire thing.
Perhaps you could rework this to make some form of factory, which returns your data loaded asynchronously? This could be as simple as making the public api for creation a factory method that returns Task<Data>, or even a generic public async Task<TData> Create<TData>(string name) where TData : Data method, which would allow you to keep the construction and loading asynchronous and avoid the blocking entirely.

Related

Avoid async from spreading in method signatures

What prevents me from constantly using the async/wait pattern in my .net code is that once you create an async method the async keyword tends to spread thru my code forcing me to make all methods async. Is there a pattern to stop this efficiently?
What prevents me from constantly using the async/wait pattern in my .net code is that once you create an async method the async keyword tends to spread thru my code forcing me to make all methods async. Is there a pattern to stop this efficiently?
Let me ask you this, then: why are you using async/await? You need to take a step back and decide if you want the benefits of asynchronous code. If you do want those benefits, then your code must be asynchronous. As soon as you block a thread, you lose all the benefits of async. So really, why use asynchronous code at all, if you're just going to block a thread anyway?
That said, there are some scenarios where a partially-async stack makes sense. For example, if your code base is temporarily in a transition state. In this case, you can use one of the hacks described in my article on brownfield async:
Blocking directly (may cause deadlocks).
Blocking on a thread pool thread (executes code on a different thread and different context, may cause unexpected parallelism).
Blocking on the current thread with a thread pool context (executes code in a different context, may cause unexpected parallelism).
Blocking on a thread with a single-threaded context (executes code on a different thread and different context).
Blocking on a nested message loop (may cause unexpected reentrancy).
All of these are hacks, and all have different drawbacks. There is no hack that works in every scenario.
As commented earlier you should go async all the way...
In some cases we use a litle helper class to cut off the async pattern. This class alows you to wait for the result without ending up with a deadlock by replacing the SynchronizationContext.
public class NoSynchronizationContextScope : IDisposable
{
private readonly SynchronizationContext synchronizationContext;
public NoSynchronizationContextScope()
{
synchronizationContext = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
}
public void Dispose() => SynchronizationContext.SetSynchronizationContext(synchronizationContext);
}
void fn()
{
using (new NoSynchronizationContextScope())
{
fnAsync().Wait();
// or
// var result = fnAsync().Result();
// in case you have to wait for a result
}
}
In the very particular case of a method that you want to start running but not wait for the result of (i.e. triggering an event handler) you can use async void. Just make sure you catch all the errors at that point:
public async void DoSomething() {
try {
var o = await DoThing1();
await DoThing2(o);
} catch (Exception e) {
// Log the error somewhere (to a file, database, etc.)
}
}
You can use async method and invoke not async method in task so outer method will behave like async and inner method is still sync.
public async Task OuterFuncAsync()
{
await Task.Run(() => InnerFunc());
}

Where does async and await end? Confusion

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

How(and why) can I avoid returning a void on these async methods?

EDIT: So it seems having the method return void instead of task means that exceptions are propagated on the wrong(unexpected?) context.
However, my IDE (Xamarin) is still kicking up a fuss on the line in my constructor where I call AttemptDatabseLoad()
"The statement is not awaited and execution of current method
continues before the call is completed. Consider using 'await'
operator or calling 'Wait' method"
Why is it kicking up this fuss? Surely the entire purpose of using an async method is precisely so that the program continues execution on the Main thread.
I've read a fair bit on async and await as I need to have some async data loading for an app i'm making. I've read in loads of places that it's bad practice to have an async method return void (excepting in cases of firing events) and I understand the reason why it can be good to keep a handle on the Task.
However, I can't see anything logically wrong with what I've written below so my question is twofold: Why is my current code poor practice? How should it be re-written?
private const int MAX_CONNECTION_ATTEMPTS = 10;
private int ConnectionAttempts = 0;
//Constructor
public DataLoader()
{
//First load up current data from local sqlite db
LoadFromLocal();
//Then go for an async load from
AttemptDatabaseLoad();
}
public async void AttemptDatabaseLoad()
{
while(ConnectionAttempts < MAX_CONNECTION_ATTEMPTS){
Task<bool> Attempt = TryLoad ();
bool success = await Attempt;
if (success) {
//call func to load data into program memory proper
}else{
ConnectionAttempts++;
}
}
}
//placeholder for now
public async Task<bool> TryLoad()
{
await Task.Delay(5000);
return false;
}
Constructor are meant to bring an object to it's fully constructed structure once initialized. On the other hand, async methods and constructors don't play well together, as a constructor is inherintly synchronous.
The way to get around this problem is usually to expose an initialization method for the type, which is itself async. Now, you let the caller initialize the object fully. Note this will require you to monitor the actual initialization of the method.
Async shines when you need scale. If you don't expect this to be an IO bottleneck in your application, perhaps consider using synchronous methods instead. This will give you the benefit of actually fully initializing your object once the constructor finishes execution. Although, I don't think I would initiate a call to a database via a constructor anyway:
public async Task InitializeAsync()
{
LoadFromLocal();
await AttemptDatabaseLoadAsync();
}
public async Task AttemptDatabaseLoadAsyncAsync()
{
while(ConnectionAttempts < MAX_CONNECTION_ATTEMPTS)
{
Task<bool> Attempt = TryLoad ();
bool success = await Attempt;
if (success)
{
//call func to load data into program memory proper
}
else
{
ConnectionAttempts++;
}
}
}
And call it:
var dataLoader = new DataLoader();
await dataLoader.InitializeAsync();
I understand the reason why it can be good to keep a handle on the Task.
So it seems having the method return void instead of task means that exceptions are propagated on the wrong(unexpected?) context.
One of the reasons it's good to have a Task is that you can use it to retrieve the results of the asynchronous method. And by "results", I don't just mean the return value - I mean exceptions, too. The Task represents the execution of that asynchronous method.
When an exception escapes an async Task method, it's placed on that returned task. When an exception escapes an async void method, there's no obvious place for it to go, so the actual behavior is to raise it directly on the SynchronizationContext that was current at the beginning of the async void method. This sounds odd, but it's specifically designed to emulate exceptions escaping event handlers.
Of course, if your async void method isn't an event handler (like this example), then the behavior seems very odd and surprising.
Why is it kicking up this fuss? Surely the entire purpose of using an async method is precisely so that the program continues execution on the Main thread.
I think you're misunderstanding the warning message. Since the Task represents the execution of that method, to ignore it is an error 99.9% of the time. By ignoring it, your code is saying that it doesn't care when the async method completes, what its return value is (if any), and whether or not it throws exceptions. It's extremely rare for code to not care about any of these.
How should it be re-written?
I have a blog post on how to do "async constructors". My favorite approach is the asynchronous factory method:
//Constructor
private DataLoader()
{
//First load up current data from local sqlite db
LoadFromLocal();
}
public static async Task<DataLoader> CreateAsync()
{
var result = new DataLoader();
await result.AttemptDatabaseLoadAsync();
return result;
}
However, since you're using this in a UI application, I suspect you'll eventually run into a situation where you want to call asynchronous code from your ViewModel constructor. Asynchronous factories are great for helper code (like DataLoader), but they don't work for ViewModels because the VMs need to be created immediately - the UI needs to show something now.
At the UI layer, you have to first initialize your UI to some kind of a "loading" state, and then update it to a "normal" state once the data has arrived. I prefer to use asynchronous data binding for this, as described in my MSDN article.
You can just change return type to Task (non-generic) and don't return "explicitly" from async method. The reasons why it's better to use void only on top-level functions can be found here: async/await - when to return a Task vs void?
So, it's mainly about recovery from exception in your async-void method. I hope it will help.
EDIT: One more thing - because I didn't notice that you're calling it from constructor. Please check also this answer: https://stackoverflow.com/a/23051370/580207 and this blog post: http://blog.stephencleary.com/2013/01/async-oop-2-constructors.html
Why is my current code poor practice?
The callers of DataLoader() constructor might experience the following issues:
Code instantiating DataLoader class is not aware that load operation is still in progress after DataLoader() returns, so it cannot use the data retrieved by async AttemptDatabaseLoad().
There is no way to discover when the loaded data becomes available.
It cannot be composed into a larger asynchronous operation.
A suggested change is to store the task returned by async method in a property so that the caller can use it to wait until load is completed, or compose it into an asynchronous method.
class DataLoader
{
public DataLoader ()
{
//First load up current data from local sqlite db
LoadFromLocal();
//Then go for an async load from
this.Completion = AttemptDatabaseLoadAsync();
}
async Task AttemptDatabaseLoadAsync()
{
while(ConnectionAttempts < MAX_CONNECTION_ATTEMPTS){
Task<bool> Attempt = TryLoad ();
bool success = await Attempt;
if (success) {
//call func to load data into program memory proper
}else{
ConnectionAttempts++;
}
}
}
public Task Completion
{
get; private set;
}
}
Usage:
var loader = new DataLoader();
loader.Completion.Wait();
or:
async Task SomeMethodAsync()
{
var loader = new DataLoader();
await loader.Completion;
}

What is the correct way to call an async method from synchronous code, and block until the task is complete? [duplicate]

This question already has answers here:
How Do I Call an Async Method from a Non-Async Method? [duplicate]
(2 answers)
How to call asynchronous method from synchronous method in C#?
(17 answers)
Closed 6 years ago.
Consider this code:
public async Task DoStuffAsync() {
await WhateverAsync(); // Stuff that might take a while
}
// Elsewhere in my project...
public async Task MyMethodAsync() {
await DoStuffAsync();
}
public void MyMethod() {
DoStuffAsync(); // <-- I want this to block until Whatever() is complete.
}
I want to provide two methods with the same functionality: an async method which runs asynchronously, and a non-async method that blocks, and either of these two methods can be called depending on whether the code I'm calling from is also async.
I don't want to repeat loads of code everywhere and create two versions of each method, wasting time and effort and reducing maintanability.
I'm guessing I can do something like one of the following:
// Call it just like any other method...
// the return type would be Task though which isn't right.
DoStuffAsync();
// Wrap it in a Task.Run(...) call, this seems ok, but
// but is doesn't block, and Task.Run(...) itself returns an
// awaitable Task... back to square one.
Task.Run(() => DoStuffAsync());
// Looks like it might work, but what if I want to return a value?
DoStuffAsync().Wait();
What is the correct way to do this?
UPDATE
Thanks for your answers. The general advice seems to be just provide an Async method and let the consumer decide, rather than creating a wrapper method.
However, let me try to explain my real-world problem...
I have a UnitOfWork class that wraps the the SaveChanges() and SaveChangesAsync() methods of an EF6 DbContext. I also have a List<MailMessage> of emails that need to be sent only when the SaveChanges() succeeds. So my code looks like this:
private readonly IDbContext _ctx;
private readonly IEmailService _email;
private readonly List<MailMessage> _emailQueue;
// ....other stuff
public void Save() {
try {
_ctx.SaveChanges();
foreach (var email in _emailQueue) _email.SendAsync(email).Wait();
} catch {
throw;
}
}
public async Task SaveAsync() {
try {
await _ctx.SaveChangesAsync();
foreach (var email in _emailQueue) await _email.SendAsync(email);
} catch {
throw;
}
}
So you can see that because an EF6 DbContext provides an async and non-async version, I kinda have to as well... Based on the answers so far, I've added .Wait() to my SendAsync(email) method, which asynchronously sends out an email via SMTP.
So... all good, apart from the deadlock problem... how do I avoid a deadlock?
What is the correct way to do this?
The correct way would be to do what you don't want to do, expose two different methods, one which is completely synchronous and another which is completely asynchronous.
Exposing async over sync and sync over async are poth anti-patterns when dealing with async code.
If the methods aren't aren't naturally async, i would expose a synchronous version only and let the invoker decide if he wants to wrap it with a Task.Run himself.
If the method is naturally async, i would expose the async method only. If you have both sync and async versions, expose them independently.
Async methods go "all the way", and they slowly bubble up and down the call stack as you use them. Embrace that fact, and you'll avoid many pitfalls along the way.
There is a Github project for that : AsyncBridge
Example included in the project homepage :
public async Task<string> AsyncString()
{
await Task.Delay(1000);
return "TestAsync";
}
public void Test()
{
string string1 = "";
string string2 = "";
using (var A = AsyncHelper.Wait)
{
A.Run(AsyncString(), res => string1 = res);
A.Run(AsyncString(), res => string2 = res);
}
}
I used it on several project without issue.
How do I do a blocking wait.
// Looks like it might work, but what if I want to return a value?
DoStuffAsync().Wait();
And it does. Regarding the
what if I want to return a value?
Suppose you also had this async method that returned a Task<string>:
public async Task<string> MyStringGetterAsync() {
return await GetStringAsync();
}
You could to the following to perform a blocking wait and retrieve its result:
var myString = MyStringGetterAsync().Result;
With regards to your intention:
I want to provide two methods with the same functionality: an async
method which runs asynchronously, and a non-async method that blocks,
and either of these two methods can be called depending on whether the
code I'm calling from is also async.
Creating a MyWhatEver() overload that just does MyWhatEverAsync.Wait() is not a recommended pattern, because it may have unintended side effects for clients calling that method, as explained e.g. here. The client calling your synchronous version of the method, might not expect its thread to be blocked as the result of calling your method, and cannot decide for itself if that is acceptable (e.g. it cannot specify ConfigureAwait). As mentioned by #Default in the comments, this could lead to deadlocks.
The same is generally true for the reverse case: i.e. having a MyWhatEverAsync() that only does return Task.Run(() => MyWhatEver()); If a client needs to, they could do this themselves and include e.g. a cancellation token, so they can control the task.
It is better to be explicit in your interface and only provide methods that do what their signature says they do.
For your real world problem (after question edit):
I have a UnitOfWork class that wraps the the SaveChanges() and
SaveChangesAsync() methods of an EF6 DbContext. I also have a
List<MailMessage> of emails that need to be sent only when the
SaveChanges() succeeds.
And (from the comments)
The success of sending an email isn't critical.
Your current UnitOfWork design for the Save and SaveAsync methods is not correct, because it violates the atomicity promises it makes.
In the scenario where "SaveChanges" succeeds, but an exception occurs on sending one of the emails. The client code calling one of the Save variants, will observe that exception, will (and should) assume that saving the changes failed, and could retry applying them.
If a client was wrapping this operation in a transaction context with a two phase commit, the "SaveChanges" would be rolled back, and when a client retries the operation, it will attempt to send the emails again, potentially causing a number of recipients to receive the email multiple times, although the changes they received the email about were not committed successfully (and may never be if sending emails fails repeatedly).
So you will need to change something.
If you really don't care about the success of sending the emails, I suggest you add the following method.
private Task SendEmailsAndIgnoreErrors(IEmailService emailService, List<MailMessage> emailQueue) {
return Task.WhenAll(emailQueue.Select(async (m) => {
try {
await emailService.SendAsync(m).ConfigureAwait(false);
} catch {
// You may want to log the failure though,
// or do something if they all/continuously fail.
}
}));
}
And use it like this:
public async Task SaveAsync() {
await _ctx.SaveChangesAsync();
await SendEmailsAndIgnoreErrors(_email, _emailQueue);
}
I would personally omit the synchronous variant, and let clients decide how to wait on the task, but if you believe you really need it, you could do this:
public void Save() {
_ctx.SaveChanges();
SendEmailsAndIgnoreErrors(_email, _emailQueue).Wait().ConfigureAwait(false);
}

How to safely wait for async method?

I've got a method which looks like this:
static async Task<string> GetGooglePage(ProxyInfo proxy)
{
using (var m=new MyNetworkClass())
{
m.Proxy = proxy;
return await m.GetAsync("http://www.google.com");
}
}
now I want to call it from method that is not async, and get the result.
The way I was trying to do it is like this:
foreach (var proxy in proxys)
{
try
{
GetGooglePage(proxy.ToProxyInfo()).Wait();
}
catch
{}
lock (Console.Out)
{
Console.Write(current++ + "\r");
}
}
My problem is that sometimes GetGooglePage(proxy.ToProxyInfo()).Wait(); deadlocks (according to visual studio debugger, there is no stack beyond this call).
I don't want to use async all the way through to Main(). How do I correctly call GetGooglePage from synchronous code without risking a deadlock?
You're running into a deadlock that I describe on my blog.
There is no standard solution for blocking on an async method, because there is no solution that works in every situation. The only officially recommended solution is to use async all the way. Stephen Toub has a good summary of workarounds here.
One approach is to execute the async method in a background thread (via Task.Run) and then Wait on that. Disadvantages of this approach are: 1) it won't work for async methods that require a specific context (e.g., write to an ASP.NET response, or update a UI); 2) changing from a synchronized context to the unsynchronized thread pool context may introduce race conditions; and 3) it burns a thread just waiting for another thread.
Another approach is to execute the async method within a nested message loop. Disadvantages of this approach are: 1) the "nested message loop" is different for every platform (WPF vs. WinForms, etc); and 2) nested loops introduce reentrancy issues (which have been responsible for many, many bugs in the Win32 era).
The best option is not to do this: if you synchronously wait for an async method, there is no reason for the method to be async in the first place. So, what you should do (assuming you really want to or have to make the top level method synchronous) is to make all the methods synchronous.
If you can't do that, then you can prevent the deadlock by using ConfigureAwait(false):
static async Task<string> GetGooglePage(ProxyInfo proxy)
{
using (var m=new MyNetworkClass())
{
m.Proxy = proxy;
return await m.GetAsync("http://www.google.com").ConfigureAwait(false);
}
}
This way, when the method resumes, it won't try resuming on the UI thread, so you won't get the deadlock. If you're using await in GetAsync() or the methods it calls, you will need to do the same thing there too.
In general, it's a good idea to use ConfigureAwait(false) everywhere, as long as you don't need to resume of the UI thread.

Categories

Resources